Contar el número de ocurrencias de elementos en la matriz de JavaScript

En esta guía, aprenderá a contar el número de ocurrencias de un solo elemento, así como todas las ocurrencias de elementos en una matriz de JavaScript, usando `for-of`, `forEach()`, `for`, `reduce()` , `countBy()` de Lodash, etc.

Introducción

Cuando trabajamos con matrices en JavaScript, con frecuencia nos encontramos con situaciones que requieren que contemos el número de ocurrencias de un elemento específico en esa matriz; este elemento podría ser una cadena, un objeto, un número o incluso un valor booleano.

En este artículo, repasaremos varios métodos para contar el número de ocurrencias de un elemento o todos los elementos en una matriz de JavaScript. También veremos cómo contar el número de ocurrencias de elementos en una matriz de matrices aplanando primero la matriz.

Cómo contar las ocurrencias de elementos usando bucles

El bucle for es uno de los métodos estándar para recorrer una matriz. Nos permite recorrer cada elemento de una matriz y compararlo con el elemento que estamos buscando. De esa forma, podemos contar el número de ocurrencias de ese elemento en una matriz. También podemos usarlo para contar el número de ocurrencias de todos los elementos en la matriz, pero cubriremos ese caso más adelante en este artículo. Por ahora, supongamos que queremos encontrar el número de ocurrencias del elemento específico.

La mejor solución: for-of Loop

Obviamente, JavaScript tiene un bucle for incorporado que podemos usar, pero, para hacer las cosas un poco más fáciles, podemos usar su modificación: el bucle for-of. De esa forma, en lugar de acceder a cada elemento por su índice en la matriz, podemos acceder al valor del elemento en sí.

{.icon aria-hidden=“true”}

Nota: JavaScript ES2015 introdujo el bucle for-of. Es una alternativa al método array.forEach(), utilizado anteriormente para iterar sobre cada elemento de una matriz y aplicar algunos cambios a cada uno de ellos. La principal diferencia entre for-of y forEach() es que el primero es compatible con las funciones async. En este artículo, hemos optado por usar principalmente el bucle for-of en lugar del método forEach() solo para estar seguros en un escenario asíncrono, pero si no le molesta eso, siéntase libre de usar forEach() en su lugar!

En primer lugar, echemos un vistazo a cuántas veces aparece un elemento específico en una matriz. Para lograr esto, debemos establecer la variable contador en 0, luego recorrer la matriz y aumentar el contador en uno cada vez que encontremos el elemento que estamos buscando. Cuando recorremos toda la matriz, el contador almacenará el número de ocurrencias del elemento que estábamos buscando:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
const allStudentsAge = [19, 22, 18, 19, 16, 18, 19, 21, 24];
let target = 19;

let counter = 0;
for (studentAge of allStudentsAge) {
  if (studentAge == target) {
        counter++;
    }
};

console.log(counter); // 3

Una situación en la que tenemos una matriz de matrices es un poco más compleja. En ese caso, primero tendremos que aplanar la matriz para que todos los elementos entren en una matriz usando el método flat():

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
const allStudentsAge = [
    [1, 19],
    [3, 4],
    [5, 19],
    [7, 8, 19],
    [10, 11, 12, 13, 14, 15],
    [19, 22, 18, 19, 16, 18, 19, 21, 24]
];

let target = 19;

let counter = 0;
for (studentAge of allStudentsAge.flat()) {
  if (studentAge == target) {
        counter++;
    }
};

console.log(counter); // 6

Esto también funciona para arreglos con elementos de diferentes tipos de datos. Vamos a crear una matriz de ejemplo con varios tipos de datos y verifiquemos si podemos contar el número de ocurrencias de un determinado elemento:

1
const myArray = [false, 24, "English", false, "english", 22, 19, false, "English", 19];

Ahora, podemos crear una función reutilizable que cuente el número de ocurrencias del elemento dado en la matriz dada:

1
2
3
4
5
6
7
8
9
const checkOccurrence = (array, element) => {
    let counter = 0;
    for (item of array.flat()) {
        if (item == element) {
            counter++;
        }
    };
    console.log(counter);
};

Comprobemos si la función que hemos creado realmente funciona:

1
2
3
checkOccurrence(myArray, false); // 3
checkOccurrence(myArray, 19); // 2
checkOccurrence(myArray, "english"); // 1

Hemos verificado que hay tres instancias del elemento falso y dos instancias del elemento 19, lo cual es correcto, pero ¿por qué solo aparece una instancia del elemento "english" en lugar de tres? Esto se debe a la sensibilidad a mayúsculas y minúsculas de la función que hemos creado; la mejor manera de resolver esto es convertir todos los elementos de la cadena a mayúsculas (o minúsculas) antes de contarlos:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
const checkOccurrence = (array, element) => {
    let counter = 0;
    for (item of array.flat()) {
        if (typeof item === "string") {
            let newItem = item.toLowerCase();
            if (newItem == element) {
                counter++;
            }
        } else {
            if (item == element) {
                counter++;
            }
        }
    };
    console.log(counter);
};

Cuando ahora contamos las ocurrencias del elemento "english", la función checkOccurrence() devuelve 3 porque ya no distingue entre mayúsculas y minúsculas:

1
checkOccurrence(myArray, "english"); // 3

Alternativa n.º 1: bucle for

Si necesita acceder al índice de cada elemento en una matriz por alguna razón, también puede usar el bucle for básico en lugar de for-of:

1
2
3
4
5
6
7
8
9
const checkOccurrence = (array, element) => {
    let counter = 0;
    for (let i = 0; i <= array.length; i++) {
        if (array[i] == element) {
            counter++;
        }
    }
    console.log(counter);
};

Podemos comprobar que esto nos da el mismo resultado que la misma función creada con el bucle for-of:

1
2
3
checkOccurrence(myArray, false); // 3
checkOccurrence(myArray, 19); // 2
checkOccurrence(myArray, "english"); // 1

Alternativa #2: forEach() Método

Otra alternativa factible es usar el método forEach() para iterar sobre todos los elementos de una matriz:

1
2
3
4
5
6
7
8
9
const checkOccurrence = (array, element) => {
    let counter = 0;
    array.forEach()for (let i = 0; i <= array.length; i++) {
        if (array[i] == element) {
            counter++;
        }
    }
    console.log(counter);
};

Esto nos daría el mismo resultado que las funciones anteriores, pero, nuevamente, tenga cuidado al usar el método forEach() en un entorno asíncrono:

1
2
3
checkOccurrence(myArray, false); // 3
checkOccurrence(myArray, 19); // 2
checkOccurrence(myArray, "english"); // 1

Comprobar el número de apariciones de todos los elementos {#verificar el número de apariciones de todos los elementos}

Hasta ahora, hemos visto cómo contar las ocurrencias de un elemento específico. Ahora, veamos cómo contar las ocurrencias de todos los elementos y devolver tanto el elemento como el número de ocurrencias como un objeto.

Para comenzar, crearemos un objeto vacío para almacenar cada elemento de la matriz como clave y el número de ocurrencias como valor. Luego recorreremos la matriz usando el bucle for-of, y en cada iteración, incrementaremos el recuento del elemento específico si ya existe en el objeto, o estableceremos el recuento en 1 de lo contrario:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
const myArray = [false, 24, "English", false, "english", 22, 19, false, "English", 19];

let counter = {};
for (element of myArray.flat()) {
    if (counter[element]) {
        counter[element] += 1;
    } else {
        counter[element] = 1;
    }
};
console.log(counter);

El código anterior generará el objeto que contiene el número de ocurrencias de cada elemento en myArray:

1
2
3
4
5
6
7
8
{
    "19": 2,
    "22": 1,
    "24": 1,
    "English": 2,
    "english": 1,
    "false": 3
}

Supongamos que todavía queremos evitar la distinción entre mayúsculas y minúsculas, podemos hacer algo como esto:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
const myArray = [false, 24, "English", false, "english", 22, 19, false, "English", 19];

let counter = {};
for (element of myArray.flat()) {
    if (typeof element === "string") {
        let newItem = element.toLowerCase();
        if (counter[newItem]) {
            counter[newItem] += 1;
        } else {
            counter[newItem] = 1;
        }
    } else {
        if (counter[element]) {
            counter[element] += 1;
        } else {
            counter[element] = 1;
        }
    }
});
console.log(counter);

Esto generará el siguiente objeto:

1
2
3
4
5
6
7
{
    "19": 2,
    "22": 1,
    "24": 1,
    "false": 3,
    "english": 3
}

Cómo contar las ocurrencias de elementos usando reduce()

reduce() es un método poderoso que se puede usar para obtener fácilmente el número de ocurrencias de cada elemento en una matriz con solo unas pocas líneas de código. Acepta una función de devolución de llamada y un valor inicial, que para nosotros es un objeto vacío para que podamos completarlo más tarde:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
const myArray = [false, 24, "English", false, "english", 22, 19, false, "English", 19];

let countObject = myArray.reduce(function (
    count,
    currentValue
) {
    return (
        count[currentValue] ? ++count[currentValue] : (count[currentValue] = 1),
        count
    );
},
{});

console.log(countObject);

Esto generaría un objeto que contiene los elementos como claves y el número de ocurrencias como valores:

1
2
3
4
5
6
7
8
{
    "19": 2,
    "22": 1,
    "24": 1,
    "false": 3,
    "English": 2,
    "english": 1
}

Cómo contar las ocurrencias de elementos mediante el método filter() {#cómo contar las ocurrencias de elementos mediante el método de filtro}

En la sección anterior, vimos cómo usar los bucles y el método reduce() para las diversas situaciones en las que podríamos querer contar el número de ocurrencias de elementos en una matriz de JavaScript. Además de los bucles y reduce(), también podemos usar otros métodos, como filter(), para determinar el número de ocurrencias de un elemento específico en una matriz.

Para lograr esto, lo filtraremos y luego llenará una matriz basada en la condición, de la cual obtendremos la longitud usando la propiedad longitud:

1
2
3
4
5
6
7
const myArray = [false, 24, "English", false, "english", 22, 19, false, "English", 19];

const itemCounter = (array, item) => {
    return array.filter((currentItem) => currentItem == item).length;
};

console.log(itemCounter(myArray, 19)); // 2

Uso de Lodash para contar ocurrencias de elementos

Probablemente sea mejor no instalar paquetes adicionales solo con el propósito de contar elementos en una matriz, pero si ya estamos usando la biblioteca Lodash en nuestro proyecto, no hay problema en usarla para contar elementos. El método .countBy() en Lodash acepta una matriz y devuelve un objeto. Este objeto contiene elementos y sus recuentos como pares clave-valor:

1
2
3
4
5
const myArray = [false, 24, "English", false, "english", 22, 19, false, "English", 19];

let lodash = _;
let elementOccurrences = _.countBy(myArray);
console.log(elementOccurrences);

Esto nos dará un objeto:

1
2
3
4
5
6
7
8
{
    "19": 2,
    "22": 1,
    "24": 1,
    "false": 3,
    "English": 2,
    "english": 1
}

Conclusión

Si necesita contar el número de ocurrencias de los elementos en una matriz, probablemente su mejor apuesta sea usar el bucle for-of como se muestra en este artículo. Es el async seguro, pero sigue siendo una forma muy simple de iterar sobre toda la matriz y contar los elementos deseados. También hemos echado un vistazo a otros enfoques alternativos: el bucle for básico, forEach() y el método filter().

Si necesita echar un vistazo a la cantidad de ocurrencias de cada elemento en una matriz, también lo tenemos cubierto: puede usar nuevamente el bucle for-of. Además, puede usar el método reduce(), o la biblioteca Lodash. sh*.