Utilizando filter() em JavaScript
Aprenda a filtrar objetos em um Array com o método filter() do JavaScript. Neste artigo o método filter() é apresentado com exemplos práticos e úteis de sua utilização.
Filtrar informações é uma das tarefas mais importantes e recorrentes enquanto programamos.
Computadores não seriam tão úteis se tivéssemos que vasculhar tudo manualmente, portanto filtrar os dados é uma tarefa comum e indispensável, permitindo que o usuário final reduza seu espaço de pesquisa a um nível aceitável.
JavaScript
é a principal linguagem de front-end
e em toda aplicação WEB será o primeiro contato do usuário com a
aplicação.
Em JavaScript
, o método filter()
nos permite filtrar items contidos em um array
, isso é feito iterando sobre os
valores existentes e retornando um novo array
apenas com aqueles objetos que atendem a determinados critérios.
A função filter()
executa uma expressão condicional em cada entrada em uma matriz:
- Se essa condicional for avaliada como
true
, o elemento será adicionado à matriz de saída. - Se a condição falhar, o elemento não será adicionado à matriz de saída.
Neste guia, veremos como trabalhar com o método filter()
do JavaScript
.
Primeiro, vamos nos familiarizar com o método, sua sintaxe e argumentos.
Em seguida, veremos vários exemplos práticos de tarefas que são facilmente abordadas com o método.
E por fim vamos compará-lo com um método alternativo(find()
) e avaliar o seu desempenho.
Valores de sintaxe e de parâmetro
A sintaxe é direta:
const arrayFiltrada = arrayOriginal.filter(funcaoFiltradora(element, index, array), context)
A funcaoFiltradora
pode ser realmente qualquer função/predicado/condição arbitrária, desde que retorne um valor
booleano, com base no valor de element
.
Tecnicamente, ele não precisa utilizar o element
em sua definição, mas isso provavelmente não seria uma função de
filtragem muito útil.
O index
e o array
são opcionais, e você provavelmente não precisará usar array
na prática.
index
é o índice do item atual e array
é um ponteiro para a matriz original.
Importante notar que a função de filtro constrói uma nova matriz e retorna todos os objetos que atendem ao critério fornecido no retorno de chamada. Ela não altera a matriz original.
Como o filter() do JavaScript funciona
Vamos dar uma olhada no método filter()
em ação.
Nas versões anteriores do JS
(antes do ES6
) uma função de retorno de chamada seria usada como:
const numeros = [1, 2, 3, 4, 5, 6];
const numerosFiltrados = numeros.filter(function (numero) {
return numero > 3;
});
console.log(numerosFiltrados); // [4, 5, 6]
A partir do ES6
, podemos simplificar isso como uma Arrow function
:
const numeros = [1, 2, 3, 4, 5, 6];
const numerosFiltrados = numeros.filter((numero) => {
return numero > 3;
});
console.log(numerosFiltrados); // [4, 5, 6]
Ou, você pode simplificar a função para ser apenas uma condicional:
const numeros = [1, 2, 3, 4, 5, 6];
const numerosFiltrados = numeros.filter((numero) => numero > 3);
console.log(numerosFiltrados); // [4, 5, 6]
Como usar o objeto context com filter()
O método filter()
pode aceitar um objeto adicional opcional: context
.
filter(funcaoFiltradora, context);
O objeto pode ser referenciado usando a palavra-chave this
de dentro da funcaoFiltradora
, e context
representa,
bem, tudo o que passamos como contexto para o filtro.
Vamos dar uma olhada em um exemplo!
Classificaremos uma lista de menu
, removendo todos os itens com preços que não estejam entre 15 e 25.
A faixa de preço é um objeto separado, que passamos para filter()
o contexto. De certa forma é normalmente usado para
definir um objeto de "configuração", contendo valores que podemos acessar genericamente, sem codificá-los:
const menu = [
{
name: "Panquecas",
price: 15.99
},
{
name: "PF",
price: 13.99
},
{
name: "Milkshake",
price: 6.99
},
{
name: "Feijoada",
price: 20.99
},
{
name: "Chambari",
price: 22.99
}
];
let priceRange = {
lower: 15,
upper: 25
};
Agora, vamos ultilizar o filter()
com a lista de menu
, passando o priceRange
como o context
:
let menuFiltrado = menu.filter(function (menu) {
return menu.price >= this.lower && menu.price <= this.upper;
}, priceRange);
console.log(menuFiltrado);
Isto resulta em:
[
{
name: "Panquecas",
price: 15.99
},
{
name: "Feijoada",
price: 20.99
},
{
name: "Chambari",
price: 22.99
}
]
Como usar o parâmetro de índice(index)
O index
pode ser usado para avaliar a posição de um elemento na matriz original.
Por exemplo, poderíamos filtrar pela posição dos elementos:
const users = ["John", "Doe", "Stephen", "Matt", "Abigail", "Susu"];
const topThree = users.filter((element, index) => {
return index <= 2;
});
console.log(topThree); // ["John", "Doe", "Stephen"]
Embora isso também possa ser alcançado acessando os últimos N
elementos de uma matriz, o índice pode desempenhar
outras funções e não ser o único critério pelo qual filtrar.
Como usar o parâmetro array
O parâmetro array
faz referência à matriz original que estamos filtrando.
Como você está iterando pela matriz de qualquer maneira, normalmente ficará satisfeito sem usar o parâmetro array
, mas
pode ser útil se a lógica depender de algum estado ou propriedade da própria matriz:
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"]
Outro exemplo poderia ser se quisermos obter metade dos elementos de um array.
Nesse caso, podemos usar o array original para obter o total de elementos para filtrar os elementos com base no valor do índice:
const halfArray = function (element, index, array) {
const half = Math.floor(array.length / 2);
return index < half;
};
Agora podemos filtrar usando halfArray
:
const names = ["John", "Doe", "Stephen", "Matt", "Abigail", "Susu"];
const halfNames = names.filter(halfArray);
console.log(halfNames); // ["John", "Doe", "Stephen"]
O método filter()
aceita uma função de predicado(filtradora), que é executada em todos os elementos do array.
Baseado no valor booleano de retorno, o element
é colocado ou não em um novo array de saída.
No final da iteração, apenas o novo array resultante é retornado, filtrado pelos critérios definidos no função de predicado.
Um objeto context
pode ser passado e muitas vezes é usado para definir um objeto de "configuração" que armazena
valores dinâmicos usados durante a filtragem.
O index
refere-se à posição do elemento atual no array original, e o array
é uma referência ao array original.
Exemplos
Com os conceitos básicos já dominados, vamos ver alguns exemplos práticos de utilização do método filter()
.
Filtrar uma matriz de objetos por valor
Filtrar um array de objetos por algum valor que eles contêm é uma das aplicações mais comuns do método filter()
.
Lidar com objetos não é muito diferente de trabalhar com outros tipos de dados!
Por exemplo, digamos que temos uma matriz de objetos de aluno, com alguns campos.
D igamos que você também queira filtrar os alunos por aqueles que se formaram no ano atual(obtido
por Date().getFullYear()
).
Você pode facilmente comparar o graduationYear
de cada um element
com o ano atual:
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);
Isto resulta em:
[
{
firstName: "John",
lastName: "Doe",
graduationYear: 2022
},
{
firstName: "Abigail",
lastName: "Susu",
graduationYear: 2022
}
]
Filtrando números primos
Vamos continuar com um exercício simples, filtrar números primos!
Vamos definir uma lista com um número definido de inteiros, e então utilizar o método filter()
:
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]
Você também pode, é claro, definir uma função primeNumbers()
que aceite um elemento e retorne true
ou false
com
base no fato de o elemento ser primo ou não e, em seguida, usar esse método na chamada filter()
, se for chamá-lo
várias vezes:
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]
Como filtrar números de uma matriz
Filtrar números em uma matriz, entre outros elementos, é tão fácil quanto verificar se uma variável é um número e retornar um valor booleano:
const isNumber = function (element) {
return Number.isFinite(element);
};
Agora podemos chamar nosso método de filtro com a função reutilizável:
const random = ['1', 'blue', 2, '-4', 0, true, -3.4];
const numbers = random.filter(isNumber);
console.log(numbers); // [2, 0, -3.4]
O método acima não é útil para números que são representados por strings, portanto, outro método pode ser primeiro
converter o elemento em um número, se aplicável(parseFloat()
) e verificar o valor convertido com Number.isFinite()
:
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]
método dfilter() vs find()
Vale a pena tirar um momento para destinguir para o o filter()
é usado e o que não é usado.
Filtrar uma lista com base em um ou mais critérios normalmente inclui o retorno de uma sublista, que se ajusta aos critérios.
Mais raramente, um único elemento, se os critérios forem muito rigorosos.
Quando você estiver procurando por um elemento em uma lista, você filtrará tudo, exceto o elemento de destino, retornado em uma lista.
Um ajuste mais natural para o último caso é utilizar o método find()
, em vez do filter()
.
filter()
: retorna uma lista de todos os elementos que "passam" o predicadofind()
: retorna o primeiro objeto que "passa" o predicado
Suponha que você tenha uma matriz de menu com diferentes categorias:
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"
}
];
São 8h e o restaurante serve apenas itens de café da manhã até as 10h. Você desejará filtrar os itens que não são do café da manhã:
let breakfastMenu = menu.filter((menu) => menu.category === "breakfast");
console.log(breakfastMenu);
Isto resulta em:
[
{
name: "buttermilk pancakes",
category: "breakfast",
price: 15.99,
status: "available"
},
{
name: "country delight",
category: "breakfast",
price: 20.99,
status: "86"
}
]
Agora, digamos que alguém está querendo pedir um country delight
.
A sublista é curta o suficiente para percebermos que o status é 86
, mas com listas mais longas - podemos querer
verificar se este item, quando encontrado, está disponível ou não:
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 :(');
}
Isto resulta em:
Sorry, the item is not available :(
Usando filter() com map()
O método map()
é usado para percorrer um array e aplicar uma função a cada elemento, retornando o resultado para um
novo array.
É um método muito comum, e combina muito bem com o filter()
.
Por exemplo, vamos filtrar alguns alunos e mapear os elementos para seus nomes e sobrenomes:
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() com indexOf()
O método indexOf()
pode ser usado para verificar se uma string começa com uma substring e retornar elementos
condicionalmente com base nisso.
Por exemplo, poderíamos filtrar uma lista de cursos de ciências, com base em se eles começam com mth
, significando que
são cursos de matemática:
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"]
Novamente, o método filter()
não altera o array original, precisamos salvar o array filtrado para trabalhar com ele
mais tarde.
Conclusão
Neste guia, examinamos como o método filter()
do JavaScript funciona e como podemos usá-lo para filtrar elementos de
uma matriz, considerando um predicado/certos critérios de filtragem.
Demos uma olhada nos argumentos que acompanham, como context
, index
e array
que permitem alterar a lógica do
predicado.
Por fim, examinamos vários exemplos e abordamos como o find()
é uma alternativa para quando você está procurando
apenas por um único elemento e como filter()
pode ser usado com outros métodos em uma cadeia.