Guía del método filter() de JavaScript

En esta guía, aprenderá a filtrar una matriz en JavaScript con el método filter(). Aprenderá cómo usar los argumentos de contexto, índice y matriz, así como también cómo encadenar filter() con map(), indexOf() y find(), a través de ejemplos prácticos de código.

Introducción

¡Filtrar la información es una de las tareas más importantes para las que usamos la automatización/computadoras! Las computadoras y el software no serían tan útiles si tuviéramos que revisar todo manualmente. Por extensión, el filtrado de datos para los usuarios finales es una tarea común, lo que permite a los usuarios reducir el espacio de búsqueda a un nivel manejable. JavaScript es el lenguaje front-end líder en el mundo y la primera frontera que ven los usuarios finales. No hace falta decir que no se puede exagerar la importancia de filtrar usando JavaScript.

En JavaScript, el método filter() nos permite filtrar a través de una matriz, iterando sobre los valores existentes y devolviendo solo los que se ajustan a ciertos criterios, en una nueva matriz.

La función filter() ejecuta una expresión condicional contra cada entrada en una matriz. Si este condicional se evalúa como “verdadero”, el elemento se agrega a la matriz de salida. Si la condición falla, el elemento no se agrega a la matriz de salida.

En esta guía, echamos un vistazo a cómo trabajar con el método filter() de JavaScript. Primero, nos familiarizaremos con el método, su sintaxis y argumentos. Luego, veremos varios ejemplos prácticos de tareas que se abordan fácilmente con el método. Finalmente, lo compararemos con un método alternativo: find() y evaluaremos su rendimiento.

Sintaxis y valores de parámetros

La sintaxis es sencilla:

1
const filteredArray = oldArray.filter(callbackFn(element, index, array), context)

El callbackFn puede ser realmente cualquier función/predicado/criterio arbitrario, siempre que devuelva un valor booleano, basado en el valor del elemento. Técnicamente, no tiene que utilizar el “elemento” en su cálculo, pero lo más probable es que no sea una función de filtrado muy útil.

index y array son opcionales, y no es muy probable que necesite usar array en la práctica. index es el índice del elemento actual, y array es un puntero a la matriz original.

{.icon aria-hidden=“true”}

Nota: La función de filtro construye una nueva matriz y devuelve todos los objetos que satisfacen el criterio dado en la devolución de llamada. No cambia la matriz original subyacente.

Cómo funciona el filtro() de JavaScript

Echemos un vistazo al método filter() en acción. En versiones anteriores de JS, antes de ES6, se usaría una función de devolución de llamada como:

1
2
3
4
5
6
const numbers = [20, 40, 17, 99, 59, 77];
const filteredNumbers = numbers.filter(function (number) {
    return number > 20;
});
  
console.log(filteredNumbers); // [40,99,59,77]

Desde ES6, podemos simplificar esto como una función de flecha:

1
2
3
4
5
6
const numbers = [20, 40, 17, 99, 59, 77];
const filteredNumbers = numbers.filter((number) => {
    return number > 20;
});
  
console.log(filteredNumbers); // [40,99,59,77]

O bien, puede colapsar la función en solo:

1
2
3
const numbers = [20, 40, 17, 99, 59, 77];
const filteredNumbers = numbers.filter((number) => number > 20);
console.log(filteredNumbers); // [40,99,59,77]

Cómo usar el objeto contexto con filtro()

El método filter() puede aceptar un objeto contexto opcional adicional:

1
filter(callbackfn, contextobj);

Se puede hacer referencia al objeto usando la palabra clave this desde dentro de la devolución de llamada, y el contexto representa, bueno, lo que sea que pasemos como el contexto para el filtro. ¡Veamos un ejemplo!

Clasificaremos a través de una lista de menú, eliminando cualquier artículo con precios que no estén entre 15 y 25. El rango de precios es un objeto separado, que pasamos al filtro() como el contexto . En cierto sentido, normalmente se usa para definir un objeto de "configuración", que contiene valores a los que podemos acceder de forma genérica, sin codificarlos de forma rígida:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const menu = [
    {
        name: "buttermilk pancakes",
        price: 15.99
    },
    {
        name: "diner double",
        price: 13.99
    },
    {
        name: "godzilla milkshake",
        price: 6.99
    },
    {
        name: "country delight",
        price: 20.99
    },
    {
        name: "egg attack",
        price: 22.99
    }
];
  
let priceRange = {
    lower: 15,
    upper: 25
};

Ahora, vamos a filtrar() la lista menú, pasando priceRange como el contexto:

1
2
3
4
5
let filteredMenu = menu.filter(function (menu) {
    return menu.price >= this.lower && menu.price <= this.upper;
}, priceRange);
  
console.log(filteredMenu);

Esto resulta en:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
[
    {
        name:"buttermilk pancakes",
        price:15.99
    },
    {
        name:"country delight",
        price:20.99
    },
    {
        name:"egg attack",
        price:22.99
    }
]

Cómo usar el parámetro índice

El índice se puede utilizar para evaluar la posición de un elemento en la matriz original. Por ejemplo, podríamos filtrar por la posición de los elementos:

1
2
3
4
5
6
7
const users = ["John", "Doe", "Stephen", "Matt", "Abigail", "Susu"];
  
const topThree = users.filter((element, index) => {
    return index <= 2;
});

console.log(topThree); // ["John", "Doe", "Stephen"]

Si bien esto también podría lograrse accediendo a los últimos N elementos de una matriz, el índice puede desempeñar otras funciones y no ser el único criterio por el cual filtrar.

Cómo usar el parámetro array

El parámetro array hace referencia a la matriz original que estamos filtrando. Dado que de todos modos está iterando a través de la matriz, normalmente estará satisfecho sin usar el parámetro array, pero puede ser útil si la lógica depende de algún estado o propiedad de la propia matriz:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
const competitors = ["John", "Doe", "Stephen", "Matt", "Abigail", "Susu"];
  
function selectWinners(name, index, array) {
   
    if (array.length > 3 && name.includes('a')) {
        return true;
    } else {
      return false;
    }
}
  
let lselectLoosers = competitors.filter((name, index, array) =>
    selectWinners(name, index, array)
);

console.log(lselectLoosers); // ["Matt", "Abigail", "Susu"]

Otro ejemplo podría ser si queremos obtener la mitad de los elementos de una matriz. En ese caso, podemos usar la matriz original para obtener el total de elementos para filtrar los elementos según el valor del índice:

1
2
3
4
const halfArray = function (element, index, array) {
    const half = Math.floor(array.length / 2);
    return index < half;
};

Ahora podemos filtrar usando halfArray:

1
2
3
const names = ["John", "Doe", "Stephen", "Matt", "Abigail", "Susu"];
const halfNames = names.filter(halfArray);
console.log(halfNames); // ["John", "Doe", "Stephen"]

En resumen, el método filter() acepta una función de predicado, que se ejecuta en cada elemento de la matriz. Según el valor de retorno booleano, el elemento se coloca o no se coloca en una nueva matriz de salida.

Al final de la iteración, solo se devuelve la nueva matriz resultante, filtrada por los criterios definidos en la función de predicado. Se puede pasar un objeto de contexto y, a menudo, se usa para definir un objeto de "configuración" que almacena valores dinámicos usados ​​durante el filtrado. El índice se refiere a la posición del elemento actual en la matriz original, y la matriz es una referencia a la matriz original.

JavaScript's filter() Ejemplos

Con la introducción fuera del camino, profundicemos en algunos ejemplos prácticos del método filter().

Filtrar una matriz de objetos por valor

Filtrar una matriz de objetos por algún valor que contengan es una de las aplicaciones más comunes del método filter().

¡Manejar objetos no es muy diferente a trabajar con otros tipos de tipos de datos!

Por ejemplo, supongamos que tenemos una matriz de objetos estudiantes, con un par de campos. Digamos que también le gustaría filtrar a los estudiantes por aquellos que se graduaron en el año actual - el obtenido por nueva Fecha().getFullYear().

Podrías comparar fácilmente el graduationYear de cada elemento con el año actual:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
const students = [
    { firstName: "John", lastName: "Doe", graduationYear : 2022 },
    { firstName: "Stephen", lastName: "Matt", graduationYear : 2023 },
    { firstName: "Abigail", lastName: "Susu", graduationYear : 2022 }
];

const currentYear = new Date().getFullYear();

let graduatingStudents = students.filter((element) => {
    if (element.graduationYear === currentYear) {
        return element;
    }
});
  
console.log(graduatingStudents);

Esto resulta en:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
[
    {
        firstName:"John",
        lastName:"Doe",
        graduationYear:2022
    },
    {
        firstName:"Abigail",
        lastName:"Susu",
        graduationYear:2022
    }
]
Filtrado de números primos mediante el filtro de matriz en JavaScript

Continuemos con un ejercicio simple: ¡filtrar números primos! Definamos una lista con un número determinado de enteros, y luego ‘filtrémosla()’:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
const myArray = [-7, -5, -2, 2, 1, 3, 12, 14, 13, 15, 70, 17, 33, 25, 27, 30, 97];
      
const primeNumbers = myArray.filter((element) => {
    for (let i = 2; element > i; i++) {
        if (element % i === 0) {
          return false;
        }
    }
    return element > 1;
});
  
console.log(primeNumbers); // [2, 3, 13, 17, 97]

Por supuesto, también podría definir una función primeNumbers(), que acepte un elemento y devuelva verdadero o falso en función de si el elemento es primo o no, y luego usar ese método en filter() llame, si lo va a llamar varias veces:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
const numbers = [-7, -5, -2, 2, 1, 3, 12, 14, 13, 15, 70, 17, 33, 25, 27, 30, 97];

function findPrimeNumbers(element) {
    for (let i = 2; element > i; i++) {
        if (element % i === 0) {
          return false;
        }
    }
    return element > 1;
}

console.log(numbers.filter(findPrimeNumbers)); // [2, 3, 13, 17, 97]
Cómo filtrar números de una matriz

Filtrar números en un array, entre otros elementos, es tan fácil como comprobar si una variable es un número, y devolver un valor booleano:

1
2
3
const isNumber = function (element) {
    return Number.isFinite(element);
};

Ahora podemos llamar a nuestro método de filtro con la función reutilizable:

1
2
3
const random = ['1', 'blue', 2, '-4', 0, true, -3.4 ];
const numbers = random.filter(isNumber);
console.log(numbers); // [2, 0, -3.4]

El método anterior no es útil para los números representados como cadenas, por lo que otro método podría ser convertir primero el elemento en un número si corresponde (parseFloat()) y verificar el valor convertido con Number.isFinite(). :

1
2
3
4
5
6
7
const isNumber = function (element) {
    return Number.isFinite(parseFloat(element));
};

const random = ['1', 'blue', 2, '-4', 0, true, -3.4 ];
const numbers = random.filter(isNumber);        
console.log(numbers); // ["1", 2, "-4", 0, -3.4]

filter() frente a find() métodos de matriz

Vale la pena tomarse un momento para apreciar para qué se usa filter() y para qué no se usa. Filtrar una lista en función de uno o más criterios normalmente incluye la devolución de una sublista que se ajuste a los criterios y, más raramente, un solo elemento, si el criterio es muy estricto. Cuando está buscando un elemento en una lista, filtraría todo excepto el elemento de destino, devuelto en una lista. Una opción más natural para esto último es buscar() el elemento, en lugar de filtrar() una lista.

  • filter() devuelve una lista de todos los elementos que "pasan" el predicado
  • find() devuelve el primer objeto que "pasa" el predicado

Suponga que tiene una variedad de menús con diferentes categorías:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
  const menu = [
    {
      name: "buttermilk pancakes",
      category: "breakfast",
      price: 15.99,
      status: "available"
    },
    {
      name: "diner double",
      category: "lunch",
      price: 13.99,
      status: "available"
    },
    {
      name: "godzilla milkshake",
      category: "shakes",
      price: 6.99,
      status: "available"
    },
    {
      name: "country delight",
      category: "breakfast",
      price: 20.99,
      status: "86"
    },
    {
      name: "egg attack",
      category: "lunch",
      price: 22.99,
      status: "available"
    }
  ];

Son las 8 a.m. y el restaurante solo sirve productos para el desayuno hasta las 10 a.m. Querrá filtrar los elementos que no son para el desayuno:

1
2
let breakfastMenu = menu.filter((menu) => menu.category === "breakfast");  
console.log(breakfastMenu);

Esto resulta en:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
[
    {
        name:"buttermilk pancakes",
        category:"breakfast",
        price:15.99,
        status:"available"
    },
    {
        name:"country delight",
        category:"breakfast",
        price:20.99,
        status:"86"
    }
]

Ahora, digamos que alguien está buscando ordenar "delicia campestre". La sublista es lo suficientemente corta como para que notemos que tiene 86, pero con listas más largas, es posible que deseemos verificar si este elemento, cuando lo encontramos, está disponible o no:

1
2
3
4
5
6
7
const delight = menu.find((menu) => menu.name === "country delight");

if (delight.status !== "86") {
    console.log('Available!');
} else {
    console.log('Sorry, the item is not available :(');
}

Esto resulta en:

1
Sorry, the item is not available :(

Usar filtro() con mapa()

El método map() se usa para iterar a través de una matriz y aplicar una función a cada elemento, devolviendo el resultado a una nueva matriz. ¡Es un método muy común, y las cadenas con filter() bien! Por ejemplo, filtremos algunos estudiantes y luego asignemos los elementos a su nombre y apellido:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
const students = [
    { firstName: "John", lastName: "Doe", grduationYear: 2022 },
    { firstName: "Stephen", lastName: "Matt", grduationYear: 2023 },
    { firstName: "Abigail", lastName: "Susu", grduationYear: 2022 }
];
  
let graduatingStudents = students
    .filter((element) => element.grduationYear === new Date().getFullYear())
    .map((item) => {
      return `${item.firstName} ${item.lastName}`;
});
  
console.log(graduatingStudents); // ["John Doe", "Abigail Susu"]

Usando filter() con indexOf()

El método indexOf() se puede usar para verificar si una cadena comienza con una subcadena y devolver elementos condicionalmente en función de si lo hacen o no. Por ejemplo, podríamos filtrar una lista de cursos de ciencias, en función de si comienzan con "mth", lo que significa que esos son cursos de matemáticas:

1
2
3
4
5
6
7
let sciCourses = ["Mth101", "Chm201", "Bio301", "Mth203", "Mth205"];
function checkCourses(courseArray, searchText) {
    return courseArray.filter(function (item) {
        return item.toLowerCase().indexOf(searchText.toLowerCase()) !== -1;
    });
}
console.log(checkCourses(sciCourses, "mth")); // ["Mth101", "Mth203", "Mth205"]

{.icon aria-hidden=“true”}

Nota: De nuevo, dado que el método filter() no muta la matriz original, necesitamos guardar la matriz filtrada para trabajar con ella más tarde.

Conclusión

En esta guía, hemos echado un vistazo a cómo funciona el método filter() de JavaScript y cómo podemos usarlo para filtrar elementos de una matriz, dado un predicado/ciertos criterios de filtrado. Hemos echado un vistazo a los argumentos que lo acompañan, como context, index y array que le permiten alterar la lógica del predicado.

Finalmente, echamos un vistazo a varios ejemplos y cubrimos find() como una alternativa para cuando solo está buscando un solo elemento, y cómo se puede usar filter() con otros métodos en una cadena.