recorrer objetos objeto metodos eliminar elementos elemento contar buscar array agregar javascript arrays unique

objetos - object to array javascript



¿Cómo obtener valores distintos de una matriz de objetos en JavaScript? (27)

Acabo de encontrar esto y pensé que es útil.

_.map(_.indexBy(records, ''_id''), function(obj){return obj})

Otra vez usando el underscore , así que si tienes un objeto como este

var records = [{_id:1,name:''one'', _id:2,name:''two'', _id:1,name:''one''}]

Sólo te dará los objetos únicos.

Lo que sucede aquí es que indexBy devuelve un mapa como este

{ 1:{_id:1,name:''one''}, 2:{_id:2,name:''two''} }

Y solo porque es un mapa, todas las claves son únicas.

Entonces solo estoy mapeando esta lista de nuevo a la matriz.

En caso de necesitar solo los distintos valores.

_.map(_.indexBy(records, ''_id''), function(obj,key){return key})

Tenga en cuenta que la key se devuelve como una cadena, por lo que si necesita enteros, debería hacerlo

_.map(_.indexBy(records, ''_id''), function(obj,key){return parseInt(key)})

Suponiendo que tengo lo siguiente:

var array = [ {"name":"Joe", "age":17}, {"name":"Bob", "age":17}, {"name":"Carl", "age": 35} ]

¿Cuál es la mejor manera de poder obtener una matriz de todas las edades distintas de manera que obtengo una matriz de resultados de:

[17, 35]

¿Hay alguna forma en la que alternativamente pueda estructurar los datos o un método mejor que no tenga que iterar a través de cada matriz, verificando el valor de "age" y verificando que otra matriz esté presente, y agregarla si no?

Si hubiera alguna manera, simplemente podría sacar las distintas edades sin iterar ...

Manera ineficiente actual Me gustaría mejorar ... Si eso significa que en lugar de "matriz" es una matriz de objetos, pero un "mapa" de objetos con alguna clave única (es decir, "1,2,3") que sería bien tambien Sólo estoy buscando la forma más eficiente de rendimiento.

La siguiente es la forma en que lo hago actualmente, pero para mí, la iteración parece ser simplemente mala para la eficiencia a pesar de que funciona ...

var distinct = [] for (var i = 0; i < array.length; i++) if (array[i].age not in distinct) distinct.push(array[i].age)


Acabo de mapear y eliminar dups:

var ages = array.map(function(obj) { return obj.age; }); ages = ages.filter(function(v,i) { return ages.indexOf(v) == i; }); console.log(ages); //=> [17, 35]

Edición: Aight! No es la forma más eficiente en términos de rendimiento, sino la IMO más sencilla y legible. Si realmente te importa la microoptimización o si tienes una gran cantidad de datos, entonces un bucle regular será más "eficiente".


Aquí hay otra manera de resolver esto:

var result = {}; for(var i in array) { result[array[i].age] = null; } result = Object.keys(result);

No tengo idea de lo rápido que se compara esta solución con las otras, pero me gusta el aspecto más limpio. ;-)

EDIT: Bueno, lo anterior parece ser la solución más lenta de todos aquí.

He creado un caso de prueba de rendimiento aquí: http://jsperf.com/distinct-values-from-array

En lugar de realizar pruebas para las edades (enteros), elegí comparar los nombres (cadenas).

Método 1 (solución de TS) es muy rápido. Curiosamente, el Método 7 supera a todas las demás soluciones, aquí simplemente me deshice de .indexOf () y usé una implementación "manual" de él, evitando las llamadas a funciones en bucle:

var result = []; loop1: for (var i = 0; i < array.length; i++) { var name = array[i].name; for (var i2 = 0; i2 < result.length; i2++) { if (result[i2] == name) { continue loop1; } } result.push(name); }

La diferencia en el rendimiento con Safari y Firefox es sorprendente, y parece que Chrome hace el mejor trabajo en optimización.

No estoy exactamente seguro de por qué los fragmentos anteriores son tan rápidos en comparación con los demás, tal vez alguien más sabio que yo tenga una respuesta. ;-)


Aquí hay una solución versátil que usa reducir, permite mapear y mantiene el orden de inserción.

elementos : una matriz

asignador : una función unaria que asigna el elemento a los criterios, o vacío para asignar el elemento en sí.

function distinct(items, mapper) { if (!mapper) mapper = (item)=>item; return items.map(mapper).reduce((acc, item) => { if (acc.indexOf(item) === -1) acc.push(item); return acc; }, []); }

Uso

const distinctLastNames = distinct(items, (item)=>item.lastName); const distinctItems = distinct(items);

Puede agregar esto a su prototipo Array y omitir el parámetro de elementos si ese es su estilo ...

const distinctLastNames = items.distinct( (item)=>item.lastName) ) ; const distinctItems = items.distinct() ;

También puede usar un Conjunto en lugar de un Array para acelerar la coincidencia.

function distinct(items, mapper) { if (!mapper) mapper = (item)=>item; return items.map(mapper).reduce((acc, item) => { acc.add(item); return acc; }, new Set()); }


Creo que estás buscando la función groupBy (usando Lodash)

_personsList = [{"name":"Joe", "age":17}, {"name":"Bob", "age":17}, {"name":"Carl", "age": 35}]; _uniqAgeList = _.groupBy(_personsList,"age"); _uniqAges = Object.keys(_uniqAgeList);

produce resultado:

17,35

Demostración de jsFiddle: http://jsfiddle.net/4J2SX/201/


El uso de las nuevas características de Ecma es excelente, pero no todos los usuarios están disponibles todavía.

El siguiente código adjuntará una nueva función con un nombre distinto al objeto Global Array. Si está intentando obtener valores distintos de una matriz de objetos, puede pasar el nombre del valor para obtener los valores distintos de ese tipo.

Array.prototype.distinct = function(item){ var results = []; for (var i = 0, l = this.length; i < l; i++) if (!item){ if (results.indexOf(this[i]) === -1) results.push(this[i]); } else { if (results.indexOf(this[i][item]) === -1) results.push(this[i][item]); } return results;};

Echa un vistazo a mi publicación en CodePen para una demostración.


Empecé a incluir el guión bajo en todos los proyectos nuevos por defecto, así que nunca tendré que pensar en estos pequeños problemas de recopilación de datos.

var array = [{"name":"Joe", "age":17}, {"name":"Bob", "age":17}, {"name":"Carl", "age": 35}]; console.log(_.chain(array).map(function(item) { return item.age }).uniq().value());

Produce [17, 35] .


La versión forEach de la respuesta de @ travis-j (útil en navegadores modernos y en el mundo de Node JS):

var unique = {}; var distinct = []; array.forEach(function (x) { if (!unique[x.age]) { distinct.push(x.age); unique[x.age] = true; } });

34% más rápido en Chrome v29.0.1547: http://jsperf.com/filter-versus-dictionary/3

Y una solución genérica que toma una función de mapeador (un poco más lenta que el mapa directo, pero eso es lo que se espera):

function uniqueBy(arr, fn) { var unique = {}; var distinct = []; arr.forEach(function (x) { var key = fn(x); if (!unique[key]) { distinct.push(key); unique[key] = true; } }); return distinct; } // usage uniqueBy(array, function(x){return x.age;}); // outputs [17, 35]


Mis dos centavos en esta función:

var result = []; for (var len = array.length, i = 0; i < len; ++i) { var age = array[i].age; if (result.indexOf(age) > -1) continue; result.push(age); }

Puede ver el resultado aquí (Método 8) http://jsperf.com/distinct-values-from-array/3


Podrías usar un enfoque de diccionario como este. Básicamente, asigna el valor que desea que sea distinto como la clave en un diccionario. Si la clave no existía, agregue ese valor como distinto.

var unique = {}; var distinct = []; for( var i in array ){ if( typeof(unique[array[i].age]) == "undefined"){ distinct.push(array[i].age); } unique[array[i].age] = 0; }

Aquí hay una demostración de trabajo: http://jsfiddle.net/jbUKP/1

Esto será O (n) donde n es el número de objetos en la matriz y m es el número de valores únicos. No hay una manera más rápida que O (n) porque debe inspeccionar cada valor al menos una vez.

Actuación

http://jsperf.com/filter-versus-dictionary Cuando ejecuté este diccionario fue un 30% más rápido.


Sólo inténtalo

var x = [] ; for (var i = 0 ; i < array.length ; i++) { if(x.indexOf(array[i][''age'']) == -1) { x.push(array[i][''age'']); } } console.log(x);


Si está utilizando ES6 / ES2015 o posterior, puede hacerlo de esta manera:

const unique = [...new Set(array.map(item => item.age))];

Here hay un ejemplo de cómo hacerlo.


Si este fuera PHP, construiría una matriz con las claves y tomaría array_keys al final, pero JS no tiene ese lujo. En su lugar, intente esto:

var flags = [], output = [], l = array.length, i; for( i=0; i<l; i++) { if( flags[array[i].age]) continue; flags[array[i].age] = true; output.push(array[i].age); }


Si tiene Array.prototype.include o está dispuesto a polyfill , esto funciona:

var ages = []; array.forEach(function(x) { if (!ages.includes(x.age)) ages.push(x.age); });


Si, como yo, prefiere un "más funcional" sin comprometer la velocidad, este ejemplo utiliza una búsqueda rápida de diccionario dentro del cierre de reducción.

var array = [ {"name":"Joe", "age":17}, {"name":"Bob", "age":17}, {"name":"Carl", "age": 35} ] var uniqueAges = array.reduce((p,c,i,a) => { if(!p[0][c.age]) { p[1].push(p[0][c.age] = c.age); } if(i<a.length-1) { return p } else { return p[1] } }, [{},[]])

Según esta test mi solución es el doble de rápida que la respuesta propuesta


Usando Lodash

var array = [ { "name": "Joe", "age": 17 }, { "name": "Bob", "age": 17 }, { "name": "Carl", "age": 35 } ]; _.chain(array).map(''age'').unique().value();

Devoluciones [17,35]


Usando las características de ES6, podrías hacer algo como:

const uniqueAges = [...new Set( array.map(obj => obj.age)) ];


Ya hay muchas respuestas válidas, pero quería agregar una que use solo el método reduce() porque es limpio y simple.

function uniqueBy(arr, prop){ return arr.reduce((a, d) => { if (!a.includes(d[prop])) { a.push(d[prop]); } return a; }, []); }

Úsalo así:

var array = [ {"name": "Joe", "age": 17}, {"name": "Bob", "age": 17}, {"name": "Carl", "age": 35} ]; var ages = uniqueBy(array, "age"); console.log(ages); // [17, 35]


así es como resolvería esto utilizando el nuevo Conjunto a través de ES6 para Typescript a partir del 25 de agosto de 2017

Array.from(new Set(yourArray.map((item: any) => item.id)))


esta función puede única matriz y objeto

function oaunic(x,n=0){ if(n==0) n = "elem"; else n = "elem."+n; var uval = []; var unic = x.filter(function(elem, index, self){ if(uval.indexOf(eval(n)) < 0){ uval.push(eval(n)); return index == self.indexOf(elem); } }) return unic; }

usa eso asi

tags_obj = [{name:"milad"},{name:"maziar"},{name:"maziar"}] tags_arr = ["milad","maziar","maziar"] console.log(oaunic(tags_obj,"name")) //for object console.log(oaunic(tags_arr)) //for array


me funciona

var items = [1,2,3,4,4,1,2,5,6,3] var uniqueItems = Array.from(new Set(items)) its return [1,2,3,4,5,6]

NB: solo para es6


underscore.js _.uniq(_.pluck(array,"age"))


usando Lodash

var array = [ { "name": "Joe", "age": 17 }, { "name": "Bob", "age": 17 }, { "name": "Carl", "age": 35 } ]; _.chain(array).pluck(''age'').unique().value(); > [17, 35]


usando ES6

let array = [ { "name": "Joe", "age": 17 }, { "name": "Bob", "age": 17 }, { "name": "Carl", "age": 35 } ]; array.map(item => item.age) .filter((value, index, self) => self.indexOf(value) === index) > [17, 35]


utilizando d3.js v3 :

ages = d3.set( array.map(function (d) { return d.age; }) ).values();


function get_unique_values_from_array_object(array,property){ var unique = {}; var distinct = []; for( var i in array ){ if( typeof(unique[array[i][property]]) == "undefined"){ distinct.push(array[i]); } unique[array[i][property]] = 0; } return distinct; }


unique(obj, prop) { let result = []; let seen = new Set(); Object.keys(obj) .forEach((key) => { let value = obj[key]; let test = !prop ? value : value[prop]; !seen.has(test) && seen.add(test) && result.push(value); }); return result; }