in

javascript – ¿Cómo contar ciertos elementos en una matriz?

apple touch icon@2

[this answer is a bit dated: read the edits]

Saluda a tus amigos: map y filter y reduce y forEach y every etc.

(Solo ocasionalmente escribo bucles for en javascript, debido a que falta el alcance a nivel de bloque, por lo que debe usar una función como el cuerpo del bucle de todos modos si necesita capturar o clonar su índice o valor de iteración. son más eficientes en general, pero a veces necesita un cierre).

La forma más legible:

[....].filter(x => x==2).length

(Podríamos haber escrito .filter(function(x){return x==2}).length en lugar de)

Lo siguiente es más eficiente en el espacio (O (1) en lugar de O (N)), pero no estoy seguro de cuánto beneficio / penalización podría pagar en términos de tiempo (no más que un factor constante desde que visita cada elemento exactamente una vez):

[....].reduce((total,x) => (x==2 ? total+1 : total), 0)

(Si necesita optimizar este fragmento de código en particular, un bucle for podría ser más rápido en algunos navegadores … puede probar cosas en jsperf.com).


Luego puede ser elegante y convertirlo en una función de prototipo:

[1, 2, 3, 5, 2, 8, 9, 2].count(2)

Como esto:

Object.defineProperties(Array.prototype, {
    count: {
        value: function(value) {
            return this.filter(x => x==value).length;
        }
    }
});

También puede colocar la antigua técnica de bucle for (ver otras respuestas) dentro de la definición de propiedad anterior (nuevamente, eso probablemente sería mucho más rápido).


2017 editar:

Vaya, esta respuesta se ha vuelto más popular que la respuesta correcta. En realidad, solo usa la respuesta aceptada. Si bien esta respuesta puede ser linda, los compiladores js probablemente no optimizan (o no pueden debido a las especificaciones) tales casos. Entonces realmente deberías escribir un bucle for simple:

Object.defineProperties(Array.prototype, {
    count: {
        value: function(query) {
            /* 
               Counts number of occurrences of query in array, an integer >= 0 
               Uses the javascript == notion of equality.
            */
            var count = 0;
            for(let i=0; i<this.length; i++)
                if (this[i]==query)
                    count++;
            return count;
        }
    }
});

Podrías definir una versión .countStrictEq(...) que usó el === noción de igualdad. ¡La noción de igualdad puede ser importante para lo que estás haciendo! (por ejemplo [1,10,3,'10'].count(10)==2, porque números como ‘4’ == 4 en javascript … de ahí que lo llamen .countEq o .countNonstrict enfatiza que usa el == operador.)

Advertencia: la definición de un nombre común en el prototipo debe hacerse con cuidado. Está bien si controlas tu código, pero está mal si todos quieren declarar el suyo. [].count función, especialmente si se comportan de manera diferente. Puede preguntarse «pero .count(query) seguramente suena bastante perfecto y canónico «… pero considere que quizás podría hacer algo como [].count(x=> someExpr of x). En ese caso, define funciones como countIn(query, container) (debajo myModuleName.countIn), o algo, o [].myModuleName_count().

También considere usar su propia estructura de datos de conjuntos múltiples (por ejemplo, como python’s ‘collections.Counter‘) para evitar tener que hacer el conteo en primer lugar. Esto funciona para coincidencias exactas del formulario [].filter(x=> x==???).length (peor de los casos SOBRE) Abajo a O (1)), y modificado agilizará las consultas del formulario [].filter(filterFunction).length (aproximadamente por un factor de # total / # duplicados).

class Multiset extends Map {
    constructor(...args) {
        super(...args);
    }
    add(elem) {
        if (!this.has(elem))
            this.set(elem, 1);
        else
            this.set(elem, this.get(elem)+1);
    }
    remove(elem) {
        var count = this.has(elem) ? this.get(elem) : 0;
        if (count>1) {
            this.set(elem, count-1);
        } else if (count==1) {
            this.delete(elem);
        } else if (count==0)
            throw `tried to remove element ${elem} of type ${typeof elem} from Multiset, but does not exist in Multiset (count is 0 and cannot go negative)`;
            // alternatively do nothing {}
    }
}

Manifestación:

> counts = new Multiset([['a',1],['b',3]])
Map(2) {"a" => 1, "b" => 3}

> counts.add('c')
> counts
Map(3) {"a" => 1, "b" => 3, "c" => 1}

> counts.remove('a')
> counts
Map(2) {"b" => 3, "c" => 1}

> counts.remove('a')
Uncaught tried to remove element a of type string from Multiset, but does not exist in Multiset (count is 0 and cannot go negative)

nota al margen: Sin embargo, si todavía quisiera la forma de programación funcional (o una línea de un solo uso sin anular Array.prototype), podría escribirlo de manera más concisa hoy en día como [...].filter(x => x==2).length. Si le preocupa el rendimiento, tenga en cuenta que, si bien es asintóticamente el mismo rendimiento que el ciclo for (tiempo O (N)), puede requerir memoria adicional O (N) (en lugar de memoria O (1)) porque casi ciertamente generar una matriz intermedia y luego contar los elementos de esa matriz intermedia.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

matplotlib demo

NumPy – Matplotlib

eTjNPqHmcHcbaH3dqM4DsW 1200 80

Los mejores villanos de Wolverine de todos los tiempos