2012-03-28 10 views
31

Dada matriz siguiente:Conde de "definido" elementos de matriz

var arr = [undefined, undefined, 2, 5, undefined, undefined]; 

me gustaría obtener el número de elementos que son definido (es decir, aquellos que son .: noundefined). Además de recorrer el conjunto, ¿hay una buena forma de hacerlo?

Respuesta

56

En navegador reciente, puede utilizar filter

var size = arr.filter(function(value) { return value !== undefined }).length; 

console.log(size); 

Otro método, si el navegador es compatible con indexOf para las matrices:

var size = arr.slice(0).sort().indexOf(undefined); 

Si por absurda que tiene uno sólo de dígitos elementos en el matriz, puede utilizar ese truco sucio:

console.log(arr.join("").length); 

Hay varios métodos que puedes usar, pero al final tenemos que ver si realmente vale la pena hacer esto en lugar de un ciclo.

+0

buena solución, pero en la experiencia siempre es mejor tomar un enfoque tan genérico como sea posible. ¡casi NUNCA confíes en la función de motor de JavaScript de un navegador! nunca. intente y se mantenga conforme a la norma de javascript (ECMA) como sea posible y tenga cuidado con los estándares más nuevos, ya que a los navegadores les lleva un tiempo implementar adecuadamente algunas características, como siempre. Al utilizar el filtro, excluyes a cualquiera que (el cielo lo prohíbe) utiliza ie9 LokizFenrir

+5

Como dijiste, deberíamos tratar de mantenernos fieles al javascript estándar (ECMAScript), ¡estoy totalmente de acuerdo contigo! Y 'filter' es parte de ECMA. Tampoco es tan nuevo (ES5, no 6). Y afortunadamente es uno de los estándares de ES que se puede polibrar fácilmente, comparar con otros. El enlace en mi respuesta también proporciona el relleno. Si nos desarrollamos para la web, mi sugerencia es siempre incluir el relleno para los métodos de ES5, bloquearnos a ES3 hoy en día no tiene sentido. – ZER0

2

No, la única manera de saber cuántos elementos no están indefinidos es recorrerlos y contarlos. Eso no significa tiene que escribir el ciclo, sin embargo, solo que algo, en algún lugar tiene que hacerlo. (Consulte el punto 3 a continuación para saber por qué agregué esa advertencia.)

La forma en que las rastrea y las cuenta depende de usted. Hay un montón de maneras:

  1. Un for bucle estándar de 0 a arr.length - 1 (ambos inclusive).
  2. A for..in bucle provided you take correct safeguards.
  3. Cualquiera de varias de las nuevas características de matriz de ECMAScript5 (siempre que esté utilizando un motor de JavaScript que las admita, o que haya incluido un calce ES5, ya que todas son regulables), como some, filter, o reduce, pasando en una función apropiada. Esto es útil no solo porque no tiene que escribir explícitamente el bucle, sino porque el uso de estas características le da al motor de JavaScript la oportunidad de optimizar el bucle internamente de varias maneras. (Si realmente lo hace variará en el motor.)

... pero todo asciende a un bucle, ya sea explícita o (en el caso de las nuevas características de la matriz) de manera implícita.

+0

¿Se considera 'Array.prototype.filter' como bucle? – RobG

+1

@RobG: Sí, porque [se define como un bucle] (http://es5.github.com/#x15.4.4.20) y, además, se requiere que sea genérico. Eso no significa que el motor del navegador no pueda pasar más rápido que el código JavaScript (y, en particular, usar 'filter' o similar permite que el motor optimice cuando sabe que se trata realmente de una matriz y no de una matriz). como objeto), pero sigue siendo un bucle. Por supuesto, en términos de lo que realmente escribimos, es menos repetitivo que un ciclo 'for' (una de las muchas razones por las que * amo * las cosas nuevas). Sin embargo, me has inspirado para agregar una advertencia. :-) –

0

Lamentablemente, no. Tendrás que pasar por un ciclo y contarlos.

EDIT:

var arrLength = arr.filter(Number); 
alert(arrLength); 

+0

@ T.J.Crowder Solucioné la respuesta. ¿Puedes verificar ahora? – blackpla9ue

+1

Ese es un ... enfoque interesante. Falla, cuenta, si uno de los elementos es '0' o' "" 'o' null' (obtiene el recuento incorrecto). Y depende de ES5, que es mejor [advierta a las personas que está haciendo] (http://meta.stackexchange.com/questions/118021/javascript-answers-using-es5-features-warn-or-not). Y sigue siendo un bucle, simplemente lo hace implícitamente en lugar de explícitamente. –

+0

@ T.J.Crowder Muchas gracias por la explicación. Edité mi respuesta – blackpla9ue

0

Loop y contar en todos los navegadores:

var cnt = 0; 
for (var i = 0; i < arr.length; i++) { 
    if (arr[i] !== undefined) { 
     ++cnt; 
    } 
} 

En los navegadores modernos:

var cnt = 0; 
arr.foreach(function(val) { 
    if (val !== undefined) { ++cnt; } 
}) 
+0

'! =' No es una buena prueba para 'undefined', confundirá' null'. –

+0

@ T.J.Crowder: cambiado a '! =='. ¡Debería saberlo mejor! – jfriend00

+0

O, si desea ser un paso más funcional: var count = arr.reduce (función (contador, valor) { valor de retorno === indefinido? Contador: contador + 1; }); – Jakob

10

Un arr ay length no es la cantidad de elementos en una matriz, es la más alta index + 1. La propiedad length informará el recuento correcto de elementos solo si hay elementos válidos en índices consecutivos.

var a = []; 
a[23] = 'foo'; 
a.length; // 24 

Dicho esto, no hay manera de excluir elementos no definidos de recuento sin necesidad de utilizar ninguna forma de un bucle.

+0

sin bucle, puede filtrar los valores indefinidos y obtener el tamaño de esa matriz. verifique mi respuesta – blackpla9ue

+0

@ blackpla9ue, estoy considerando solo el lenguaje JavaScript central sin la biblioteca JQuery. La pregunta solo está etiquetada javascript. – taskinoor

+1

@ blackpla9ue: Su aproximación se repite, simplemente lo hace en el código jQuery (originalmente) o dentro de 'filter' (su actualización actual, que no funciona, por cierto). –

0

Si la década de los indefinidos están implícitos entonces usted puede hacer:

var len = 0; 
for (var i in arr) { len++ }; 

de indefinidos están implícitas si no se establece de manera explícita

//both are a[0] and a[3] are explicit undefined 
var arr = [undefined, 1, 2, undefined]; 

arr[6] = 3; 
//now arr[4] and arr[5] are implicit undefined 

delete arr[1] 
//now arr[1] is implicit undefined 

arr[2] = undefined 
//now arr[2] is explicit undefined 
0

Eliminar los valores a continuación, comprobar (quita cheque nulo aquí si desea)

const x = A.filter(item => item !== undefined || item !== null).length 

Con Lodash

const x = _.size(_.filter(A, item => !_.isNil(item)))