recorrer objetos objeto lista elementos crear buscar array agregar javascript performance properties count key

lista - recorrer array de objetos javascript



¿Cómo contar de manera eficiente el número de claves/propiedades de un objeto en JavaScript? (19)

¿Cuál es la forma más rápida de contar el número de claves / propiedades de un objeto? ¿Es posible hacer esto sin iterar sobre el objeto? es decir, sin hacer

var count = 0; for (k in myobj) if (myobj.hasOwnProperty(k)) count++;

(Firefox proporcionó una propiedad mágica __count__ , pero esto se eliminó en algún lugar de la versión 4).


De: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

Object.defineProperty (obj, prop, descriptor)

Puedes agregarlo a todos tus objetos:

Object.defineProperty(Object.prototype, "length", { enumerable: false, get: function() { return Object.keys(this).length; } });

O un solo objeto:

var myObj = {}; Object.defineProperty(myObj, "length", { enumerable: false, get: function() { return Object.keys(this).length; } });

Ejemplo:

var myObj = {}; myObj.name = "John Doe"; myObj.email = "[email protected]"; myObj.length; //output: 2

Agregado de esa manera, no se mostrará en for..in loops:

for(var i in myObj) { console.log(i + ":" + myObj[i]); }

Salida:

name:John Doe email:[email protected]

Nota: no funciona en <navegadores IE9.



Intento ponerlo a disposición de todos los objetos como este:

Object.defineProperty(Object.prototype, "length", { get() { if (!Object.keys) { Object.keys = function (obj) { var keys = [],k; for (k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) { keys.push(k); } } return keys; }; } return Object.keys(this).length; },}); console.log({"Name":"Joe","Age":26}.length) //returns 2


La forma en que resolví este problema es construir mi propia implementación de una lista básica que mantiene un registro de cuántos elementos se almacenan en el objeto. Es muy sencillo. Algo como esto:

function BasicList() { var items = {}; this.count = 0; this.add = function(index, item) { items[index] = item; this.count++; } this.remove = function (index) { delete items[index]; this.count--; } this.get = function(index) { if (undefined === index) return items; else return items[index]; } }


La implementación estándar del Objeto ( Propiedades y Métodos Internos del Objeto ES5.1 ) no requiere que un Object realice un seguimiento de su número de claves / propiedades, por lo que no debería haber una manera estándar de determinar el tamaño de un Object sin iterar explícita o implícitamente sobre sus claves .

Así que aquí están las alternativas más utilizadas:

1. Object.keys de ECMAScript ()

Object.keys(obj).length; Funciona mediante la iteración interna de las claves para calcular una matriz temporal y devuelve su longitud.

  • Pros - Sintaxis legible y limpia. No se requiere una biblioteca o código personalizado, excepto un shim si el soporte nativo no está disponible
  • Contras - sobrecarga de memoria debido a la creación de la matriz.

2. Soluciones basadas en bibliotecas.

Muchos ejemplos basados ​​en bibliotecas en otras partes de este tema son modismos útiles en el contexto de su biblioteca. Sin embargo, desde el punto de vista del rendimiento, no hay nada que ganar en comparación con un código perfecto sin biblioteca, ya que todos esos métodos de biblioteca en realidad encapsulan un Object.keys -for-loop o ES5 Object.keys (nativo o shimmed).

3. Optimizando un bucle for

La parte más lenta de dicho bucle for es generalmente la llamada .hasOwnProperty() , debido a la función de sobrecarga de llamada. Entonces, cuando solo quiero el número de entradas de un objeto JSON, simplemente .hasOwnProperty() llamada .hasOwnProperty() si sé que ningún código no extendió el Object.prototype .

De lo contrario, su código podría optimizarse muy ligeramente al hacer k local ( var k ) y al usar el operador de incremento de prefijo ( ++count ) en lugar de postfix.

var count = 0; for (var k in myobj) if (myobj.hasOwnProperty(k)) ++count;

Otra idea se basa en el almacenamiento en caché del método hasOwnProperty :

var hasOwn = Object.prototype.hasOwnProperty; var count = 0; for (var k in myobj) if (hasOwn.call(myobj, k)) ++count;

Si esto es más rápido o no en un entorno dado es una cuestión de evaluación comparativa. De todos modos, se puede esperar una ganancia de rendimiento muy limitada.


No conozco ninguna forma de hacer esto, sin embargo, para mantener las iteraciones al mínimo, puede intentar verificar la existencia de __count__ y, si no existe (es decir, no Firefox), puede iterar sobre el objeto y Definirlo para su uso posterior, por ejemplo:

if (myobj.__count__ === undefined) { myobj.__count__ = ... }

De esta manera, cualquier navegador que soporte __count__ usaría eso, y las iteraciones solo se llevarían a cabo para aquellos que no lo hacen. Si el recuento cambia y no puede hacer esto, siempre puede convertirlo en una función:

if (myobj.__count__ === undefined) { myobj.__count__ = function() { return ... } myobj.__count__.toString = function() { return this(); } }

De esta manera en cualquier momento te refieres a myobj. __count__ la función se disparará y recalculará.


No creo que esto sea posible (al menos no sin usar algunos elementos internos). Y no creo que ganes mucho optimizando esto.


Para aquellos que tengan Ext JS 4 en su proyecto puedes hacer:

Ext.Object.getSize(myobj);

La ventaja de esto es que funcionará en todos los navegadores compatibles con Ext (IE6-IE8 incluido), sin embargo, creo que el tiempo de ejecución no es mejor que el O (n), al igual que con otras soluciones sugeridas.


Para aquellos que tienen Underscore.js incluido en su proyecto, usted puede hacer:

_({a:'''', b:''''}).size() // => 2

o estilo funcional:

_.size({a:'''', b:''''}) // => 2



Para iterar en Avi Flax, responda Object.keys (obj) .length es correcto para un objeto que no tiene funciones vinculadas a él

ejemplo:

obj = {"lol": "what", owo: "pfft"}; Object.keys(obj).length; // should be 2

versus

arr = []; obj = {"lol": "what", owo: "pfft"}; obj.omg = function(){ _.each(obj, function(a){ arr.push(a); }); }; Object.keys(obj).length; // should be 3 because it looks like this /* obj === {"lol": "what", owo: "pfft", omg: function(){_.each(obj, function(a){arr.push(a);});}} */

pasos para evitar esto:

  1. No ponga funciones en un objeto en el que desee contar el número de teclas

  2. use un objeto separado o cree un nuevo objeto específicamente para funciones (si desea contar cuántas funciones hay en el archivo utilizando Object.keys(obj).length )

También sí, utilicé el módulo _ o guión bajo de nodejs en mi ejemplo

La documentación se puede encontrar aquí Underscore.js , así como su fuente en github y otra información adicional

Y finalmente, una implementación de lodash https://lodash.com/docs#size

_.size(obj)


Podrías usar este código:

if (!Object.keys) { Object.keys = function (obj) { var keys = [], k; for (k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) { keys.push(k); } } return keys; }; }

Entonces puedes usar esto también en navegadores antiguos:

var len = Object.keys(obj).length;


Puede usar Object.keys(data).length para encontrar la longitud del objeto JSON que tiene datos clave


Puede usar: Object.keys(objectName).length; & Object.values(objectName).length; Object.keys(objectName).length; & Object.values(objectName).length;


Según lo indicado por Avi Flax https://.com/a/4889658/1047014

Object.keys(obj).length

hará el truco para todas las propiedades enumerables en su objeto, pero para incluir también las propiedades no enumerables, puede usar los Object.getOwnPropertyNames . Aquí está la diferencia:

var myObject = new Object(); Object.defineProperty(myObject, "nonEnumerableProp", { enumerable: false }); Object.defineProperty(myObject, "enumerableProp", { enumerable: true }); console.log(Object.getOwnPropertyNames(myObject).length); //outputs 2 console.log(Object.keys(myObject).length); //outputs 1 console.log(myObject.hasOwnProperty("nonEnumerableProp")); //outputs true console.log(myObject.hasOwnProperty("enumerableProp")); //outputs true console.log("nonEnumerableProp" in myObject); //outputs true console.log("enumerableProp" in myObject); //outputs true

Como se indica aquí, tiene el mismo soporte de navegador que Object.keys

Sin embargo, en la mayoría de los casos, es posible que no desee incluir los no insumibles en este tipo de operaciones, pero siempre es bueno saber la diferencia;)


Si está usando Underscore.js , puede usar _.size (gracias @douwe):
_.size(obj)

Alternativamente, también puede usar _.keys que podrían ser más claros para algunos:
_.keys(obj).length

Recomiendo encarecidamente Underscore, es una biblioteca apretada para hacer muchas cosas básicas. Siempre que sea posible, coinciden con ECMA5 y difieren a la implementación nativa.

De lo contrario apoyo la respuesta de @ Avi. Lo edité para agregar un enlace al documento MDC que incluye el método keys () que puede agregar a navegadores que no sean ECMA5.


Si jQuery anterior no funciona, intente

$(Object.Item).length


Si realmente tiene un problema de rendimiento, sugeriría ajustar las llamadas que agregan / eliminan propiedades del objeto con una función que también incremente / disminuya una propiedad con el nombre apropiado (¿tamaño?).

Solo necesita calcular el número inicial de propiedades una vez y continuar desde allí. Si no hay un problema de rendimiento real, no te molestes. Simplemente envuelva ese bit de código en una función getNumberOfProperties(object) y getNumberOfProperties(object) con él.


como se respondió anteriormente: Object.keys(obj).length

Pero: como ahora tenemos una clase de Map real en ES6, suggest usarla en lugar de usar las propiedades de un objeto.

const map = new Map(); map.set("key", "value"); map.size; // THE fastest way