Aquí hay 3 formas de filtrar duplicados de una matriz y devolver solo los valores únicos. Mi favorito es usar Set porque es el más corto y simple 😁
const array = ;// 1: "Set";// 2: "Filter"array.filter((item, index) => array.indexOf(item) === index);// 3: "Reduce"array.reduce( (unique, item) => (unique.includes(item) ? unique : ), ,);// RESULT:// ;
# 1. Usando set
Permítanme comenzar primero explicando qué es Set:
Set
es un nuevo objeto de datos introducido en ES6. Porque Set
solo le permite almacenar valores únicos. Cuando pase un array, eliminará cualquier valor duplicado.
Bien, volvamos a nuestro código y desglosemos lo que está sucediendo. Hay 2 cosas pasando:
- Primero, estamos creando un nuevo
Set
pasando un array. Dado queSet
solo permite valores únicos, se eliminarán todos los duplicados. - Ahora que los duplicados se han ido, vamos a convertirlos de nuevo en una matriz utilizando el operador de propagación
...
const array = ;// Step 1const uniqueSet = new Set(array);// Set { '🐑', 1, 2, 3 }// Step 2const backToArray = ;//
# Convierta el conjunto a una matriz utilizando Array.desde
Alternativamente, también puede usar Array.from
para convertir un Set
en una matriz:
const array = ;Array.from(new Set(array));//
# 2: Usando filter
Para entender esta opción, repasemos lo que están haciendo estos dos métodos: indexOf
y filter
# indexOf
El método indexOf
devuelve el primer índice que encuentra del elemento proporcionado de nuestro array.
const array = ;array.indexOf('🐑'); // 0array.indexOf(1); // 1array.indexOf(2); // 2array.indexOf(3); // 5
# filtro
El método filter()
crea una nueva matriz de elementos que pasan el condicional que proporcionamos. En otras palabras, si el elemento pasa y devuelve true
, se incluirá en la matriz filtrada. Y cualquier elemento que falle o devuelva false
, no estará en la matriz filtrada.
Entremos y pasemos por lo que sucede a medida que recorremos el array.
const array = ;array.filter((item, index) => { console.log( // a. Item item, // b. Index index, // c. indexOf array.indexOf(item), // d. Condition array.indexOf(item) === index, ); return array.indexOf(item) === index;});
A continuación se muestra la salida de la consola.registro mostrado arriba. Los duplicados son donde el índice no coincide con el indexOf. Así que en esos casos, la condición será falsa y no se incluirá en nuestra matriz filtrada.
Item | Index | indexOf | Condition |
---|---|---|---|
🐑 | 0 | 0 | true |
1 | 1 | 1 | true |
2 | 2 | 2 | true |
🐑 | 3 | 0 | false |
🐑 | 4 | 0 | false |
3 | 5 | 5 | true |
# Recuperar los valores duplicados
También podemos usar el método filter para recuperar los valores duplicados de la matriz. Podemos hacer esto simplemente ajustando nuestra condición de esta manera:
const array = ;array.filter((item, index) => array.indexOf(item) !== index);//
Una vez más, vamos a pasar por esto y ver la salida:
Item | Index | indexOf | Condition |
---|---|---|---|
🐑 | 0 | 0 | false |
1 | 1 | 1 | false |
2 | 2 | 2 | false |
🐑 | 3 | 0 | true |
🐑 | 4 | 0 | true |
3 | 5 | 5 | false |
# 3: Usando reducir
El método reduce
se usa para reducir los elementos de la matriz y combinarlos en una matriz final basada en alguna función reductora que pase.
En este caso, nuestra función reductora está comprobando si nuestra matriz final contiene el elemento. Si no lo hace, pon ese objeto en nuestra matriz final. De lo contrario, omita ese elemento y devuelva solo nuestra matriz final tal cual (esencialmente omitiendo ese elemento).
Reducir siempre es un poco más difícil de entender, así que también pasemos a cada caso y veamos la salida:
const array = ;array.reduce((unique, item) => { console.log( // a. Item item, // b. Final Array (Accumulator) unique, // c. Condition (Remember it only get pushed if this returns `false`) unique.includes(item), // d. Reducer Function Result unique.includes(item) ? unique : , ); return unique.includes(item) ? unique : ;}, ); // 👈 The initial value of our Accumulator is an empty array// RESULT:// ;
Y aquí está la salida de la consola.registro:
Artículo | Acumulador (ANTES de la Función Reductora) | ¿Empujar al Acumulador? | Acumulador (DESPUÉS de la Función reductora) |
---|---|---|---|
🐑 |
|
Sí |
|
1 |
|
Sí |
|
2 |
|
Sí |
|
🐑 |
|
No |
|
🐑 |
|
No |
|
3 |
|
Sí |
|
# Aportaciones de la comunidad
-
@smokkku:
array.includes(item)
es una forma más idiomática de probar si la matriz contiene el elemento -
@riquelkovsky: Justo hoy hice esto haciendo lo siguiente.
Object.keys(array.reduce((map, next) => ({...map, : true}), {}))
-@luisiacc2: Claro, Set()
hará el truco para los valores primitivos, con objetos una solución que no sea O(n^2)
primero realizaría un sort()
en la matriz (que opera en O(nlogn)
), y luego buscaría los elementos iguales adyacentes(que es O(n)
), para obtener O(n + nlogn)
.
-
@iamdipankarj: También,
Array.from(new Set())
, pero esto solo funciona en primitivas. Para filtrar duplicados en una matriz de objetos personalizados.filter()
es el camino a seguir. -
@benawad:
filter
el tiempo de ejecución esO(n^2)