JavaScript
Tutorial JavaScript: Filtrado con filter() y find()
JavaScript filtrado: técnicas y ejemplos. Aprende técnicas de filtrado en JavaScript con ejemplos prácticos y detallados.
Aprende JavaScript y certifícateFundamentos de filtrado en arrays: Sintaxis y diferencias entre filter() y find()
Los arrays en JavaScript ofrecen métodos integrados para buscar y filtrar elementos según criterios específicos. Dos de los más útiles son filter()
y find()
, que aunque parecen similares, tienen propósitos y comportamientos distintos.
Método filter()
El método filter()
examina todos los elementos de un array y devuelve un nuevo array con aquellos que cumplen una condición determinada. Este método no modifica el array original, siguiendo los principios de la programación funcional.
La sintaxis básica es:
const newArray = array.filter(callback);
Donde callback
es una función que se ejecuta para cada elemento y debe devolver true
o false
. El callback recibe tres parámetros:
array.filter((element, index, array) => {
// Lógica que devuelve true o false
});
element
: El elemento actual que se está procesandoindex
: La posición del elemento en el arrayarray
: El array completo sobre el que se llamó a filter()
Veamos un ejemplo práctico:
const numbers = [1, 2, 3, 4, 5, 6, 7, 8];
const evenNumbers = numbers.filter(num => num % 2 === 0);
console.log(evenNumbers); // [2, 4, 6, 8]
En este caso, filter()
crea un nuevo array que contiene solo los números pares del array original.
También podemos filtrar objetos basándonos en sus propiedades:
const products = [
{ name: 'Laptop', price: 1200, inStock: true },
{ name: 'Phone', price: 800, inStock: false },
{ name: 'Tablet', price: 500, inStock: true }
];
const availableProducts = products.filter(product => product.inStock);
console.log(availableProducts); // [{ name: 'Laptop'... }, { name: 'Tablet'... }]
Método find()
A diferencia de filter()
, el método find()
devuelve el primer elemento que cumple con la condición especificada. Si ningún elemento cumple la condición, devuelve undefined
.
La sintaxis es similar a filter()
:
const element = array.find(callback);
El callback recibe los mismos parámetros que en filter()
:
array.find((element, index, array) => {
// Lógica que devuelve true o false
});
Veamos un ejemplo:
const numbers = [5, 12, 8, 130, 44];
const firstLargeNumber = numbers.find(num => num > 10);
console.log(firstLargeNumber); // 12
Observa que aunque hay varios números mayores que 10 en el array, find()
solo devuelve el primero que encuentra (12).
Para buscar objetos por sus propiedades:
const users = [
{ id: 1, name: 'Alice', role: 'admin' },
{ id: 2, name: 'Bob', role: 'user' },
{ id: 3, name: 'Charlie', role: 'user' }
];
const admin = users.find(user => user.role === 'admin');
console.log(admin); // { id: 1, name: 'Alice', role: 'admin' }
Diferencias clave entre filter() y find()
Valor de retorno:
filter()
devuelve un array (posiblemente vacío), mientras quefind()
devuelve un único elemento oundefined
.Comportamiento de búsqueda:
filter()
examina todos los elementos del array, mientras quefind()
se detiene en cuanto encuentra el primer elemento que cumple la condición.Caso de no coincidencia: Si ningún elemento cumple la condición,
filter()
devuelve un array vacío[]
, mientras quefind()
devuelveundefined
.
const numbers = [1, 3, 5, 7];
// Ningún número es par
const evenNumbers = numbers.filter(num => num % 2 === 0);
console.log(evenNumbers); // []
const firstEven = numbers.find(num => num % 2 === 0);
console.log(firstEven); // undefined
- Rendimiento: Para grandes conjuntos de datos,
find()
puede ser más eficiente cuando solo necesitas el primer elemento que coincida, ya que deja de iterar una vez que lo encuentra.
Cuándo usar cada método
Usa filter()
cuando:
- Necesites todos los elementos que cumplan una condición
- Quieras crear un subconjunto de datos basado en ciertos criterios
- Debas realizar operaciones posteriores sobre múltiples elementos filtrados
// Obtener todos los productos con descuento para mostrarlos en una sección especial
const discountedProducts = products.filter(product => product.discount > 0);
Usa find()
cuando:
- Busques un elemento específico (como un usuario por ID)
- Solo necesites la primera coincidencia
- Sepas que solo existe un elemento que cumple la condición
// Buscar un producto específico por su ID
const product = inventory.find(item => item.id === productId);
Predicados simples
Los predicados son las funciones que devuelven true
o false
y que pasamos a filter()
o find()
. Para casos sencillos, podemos usar expresiones lambda (funciones flecha):
// Predicado simple con filter()
const adults = people.filter(person => person.age >= 18);
// Predicado simple con find()
const sarah = people.find(person => person.name === 'Sarah');
Estos métodos de filtrado son fundamentales para el manejo de datos en JavaScript moderno y constituyen la base para operaciones más complejas de transformación y procesamiento de colecciones.
Construcción de predicados eficientes: Funciones de filtrado para casos simples y complejos
Los predicados son funciones que evalúan una condición y devuelven un valor booleano, siendo fundamentales para las operaciones de filtrado en JavaScript. Construir predicados eficientes mejora tanto la legibilidad como el rendimiento de nuestro código.
Predicados para casos simples
Para situaciones básicas, las funciones flecha ofrecen una sintaxis concisa y expresiva:
// Filtrar números positivos
const positiveNumbers = numbers.filter(num => num > 0);
// Encontrar el primer producto disponible
const firstAvailable = products.find(product => product.available);
Cuando necesitamos reutilizar predicados, es recomendable extraerlos como funciones independientes:
// Predicado reutilizable
const isPremiumUser = user => user.subscription === 'premium';
// Uso en múltiples contextos
const premiumUsers = users.filter(isPremiumUser);
const firstPremiumUser = users.find(isPremiumUser);
Esta técnica mejora la mantenibilidad del código y facilita las pruebas unitarias de la lógica de filtrado.
Predicados parametrizados
Para crear filtros más flexibles, podemos implementar funciones que generen predicados:
// Generador de predicados para filtrar por precio
const priceAbove = threshold => product => product.price > threshold;
// Uso con diferentes umbrales
const expensiveProducts = products.filter(priceAbove(1000));
const midRangeProducts = products.filter(priceAbove(500));
Este patrón aprovecha los cierres (closures) de JavaScript para crear predicados configurables según nuestras necesidades.
Predicados compuestos
Para condiciones más complejas, podemos combinar predicados mediante operadores lógicos:
// Predicados individuales
const isInStock = product => product.stock > 0;
const isOnSale = product => product.discount > 0;
// Combinación con operadores lógicos
const availableDeals = products.filter(product => isInStock(product) && isOnSale(product));
También podemos crear funciones de composición para mejorar la legibilidad:
// Funciones para componer predicados
const and = (predA, predB) => item => predA(item) && predB(item);
const or = (predA, predB) => item => predA(item) || predB(item);
const not = pred => item => !pred(item);
// Uso de predicados compuestos
const isExpensive = product => product.price > 1000;
const isExpensiveAndInStock = and(isExpensive, isInStock);
const budgetOrOnSale = or(not(isExpensive), isOnSale);
const premiumAvailable = products.filter(isExpensiveAndInStock);
const goodDeals = products.filter(budgetOrOnSale);
Optimización de predicados
Para mejorar el rendimiento en conjuntos de datos grandes, podemos implementar estrategias de optimización:
- Evaluación temprana: Colocar las condiciones más discriminantes primero
// Menos eficiente: evaluación compleja primero
const inefficientFilter = items.filter(item =>
complexCalculation(item) && item.simple === true
);
// Más eficiente: evaluación simple primero
const efficientFilter = items.filter(item =>
item.simple === true && complexCalculation(item)
);
- Evitar cálculos redundantes en predicados:
// Ineficiente: recalcula para cada elemento
const inefficient = data.filter(item => {
const result = expensiveOperation();
return item.value > result;
});
// Eficiente: calcula una sola vez
const threshold = expensiveOperation();
const efficient = data.filter(item => item.value > threshold);
Predicados para estructuras anidadas
Para filtrar datos con estructuras complejas, podemos crear predicados específicos:
// Filtrar por propiedad anidada
const hasActiveTasks = user =>
user.tasks && user.tasks.some(task => task.status === 'active');
const usersWithPendingWork = users.filter(hasActiveTasks);
También podemos implementar búsquedas profundas en estructuras jerárquicas:
// Buscar comentarios de un autor específico en una estructura anidada
const findCommentsByAuthor = authorId => {
const searchComments = item => {
// Verificar el elemento actual
if (item.author === authorId) return true;
// Buscar recursivamente en respuestas
if (item.replies && item.replies.length > 0) {
return item.replies.some(searchComments);
}
return false;
};
return searchComments;
};
const aliceComments = comments.filter(findCommentsByAuthor('alice123'));
Predicados con contexto
En ocasiones necesitamos acceder a un contexto durante el filtrado:
// Filtrar elementos relacionados con el elemento seleccionado
function getRelatedItems(items, selectedId) {
const selectedItem = items.find(item => item.id === selectedId);
if (!selectedItem) return [];
return items.filter(item =>
item.id !== selectedId &&
item.category === selectedItem.category
);
}
const relatedProducts = getRelatedItems(catalog, 'prod-457');
Predicados para casos de uso específicos
Para búsquedas de texto, podemos crear predicados que manejen diferentes casos:
// Búsqueda insensible a mayúsculas/minúsculas
const containsText = searchText => item => {
const search = searchText.toLowerCase();
return item.title.toLowerCase().includes(search) ||
item.description.toLowerCase().includes(search);
};
const searchResults = items.filter(containsText('javascript'));
Para filtrado por rango de valores:
// Filtrar por rango de precios
const priceRange = (min, max) => product =>
product.price >= min && product.price <= max;
const midRangeItems = products.filter(priceRange(100, 500));
Estos patrones de construcción de predicados nos permiten crear filtros expresivos y mantenibles que se adaptan a la complejidad de nuestros datos y requisitos de negocio.
Integración con el ecosistema funcional: Combinación de filter() y find() con otros métodos de array
La verdadera potencia de los métodos filter()
y find()
se manifiesta cuando los combinamos con otros métodos funcionales de arrays en JavaScript. Esta integración permite crear flujos de procesamiento de datos elegantes y expresivos que transforman, filtran y extraen información de manera declarativa.
Encadenamiento de métodos funcionales
El encadenamiento (chaining) es una técnica fundamental en programación funcional que permite aplicar múltiples operaciones secuenciales a una colección de datos:
const transactions = [
{ id: 1, amount: 100, type: 'purchase', category: 'food' },
{ id: 2, amount: 50, type: 'refund', category: 'electronics' },
{ id: 3, amount: 200, type: 'purchase', category: 'electronics' },
{ id: 4, amount: 25, type: 'purchase', category: 'food' }
];
// Obtener el total de compras en electrónica
const totalElectronicsPurchases = transactions
.filter(t => t.type === 'purchase' && t.category === 'electronics')
.map(t => t.amount)
.reduce((sum, amount) => sum + amount, 0);
console.log(totalElectronicsPurchases); // 200
En este ejemplo, combinamos filter()
para seleccionar transacciones específicas, map()
para extraer los montos y reduce()
para sumarlos, creando un pipeline de datos claro y conciso.
Combinación con map() para transformación
La combinación de filter()
con map()
permite filtrar y transformar datos en una secuencia fluida:
const products = [
{ id: 1, name: 'Laptop', price: 1200, stock: 5 },
{ id: 2, name: 'Phone', price: 800, stock: 0 },
{ id: 3, name: 'Tablet', price: 500, stock: 12 },
{ id: 4, name: 'Headphones', price: 150, stock: 8 }
];
// Obtener nombres de productos disponibles con precio formateado
const availableProductsInfo = products
.filter(p => p.stock > 0)
.map(p => ({
name: p.name,
formattedPrice: `$${p.price.toFixed(2)}`
}));
console.log(availableProductsInfo);
// [
// { name: 'Laptop', formattedPrice: '$1200.00' },
// { name: 'Tablet', formattedPrice: '$500.00' },
// { name: 'Headphones', formattedPrice: '$150.00' }
// ]
Uso de find() con destructuring
Podemos combinar find()
con destructuring para extraer elementos específicos de manera elegante:
const users = [
{ id: 1, name: 'Alice', permissions: ['read', 'write'] },
{ id: 2, name: 'Bob', permissions: ['read'] },
{ id: 3, name: 'Charlie', permissions: ['admin', 'read', 'write'] }
];
// Buscar un usuario con permisos de administrador
const { name, permissions } = users.find(user =>
permissions.includes('admin')
) || { name: 'Unknown', permissions: [] };
console.log(`Admin user: ${name}`); // Admin user: Charlie
El operador ||
proporciona un valor predeterminado en caso de que no se encuentre ningún usuario administrador.
Integración con sort() para filtrado y ordenamiento
Combinar filter()
con sort()
permite filtrar y ordenar datos en una sola cadena de operaciones:
const tasks = [
{ id: 1, title: 'Fix bug', priority: 'high', completed: false },
{ id: 2, title: 'Write docs', priority: 'medium', completed: true },
{ id: 3, title: 'Test feature', priority: 'high', completed: false },
{ id: 4, title: 'Deploy app', priority: 'medium', completed: false }
];
// Obtener tareas pendientes ordenadas por prioridad
const pendingTasksByPriority = tasks
.filter(task => !task.completed)
.sort((a, b) => {
const priorityValues = { high: 3, medium: 2, low: 1 };
return priorityValues[b.priority] - priorityValues[a.priority];
});
console.log(pendingTasksByPriority.map(t => t.title));
// ['Fix bug', 'Test feature', 'Deploy app']
Combinación con some() y every()
Los métodos filter()
y find()
se complementan perfectamente con some()
y every()
para validaciones complejas:
const team = [
{ name: 'Alice', skills: ['javascript', 'react', 'node'] },
{ name: 'Bob', skills: ['python', 'data analysis'] },
{ name: 'Charlie', skills: ['javascript', 'vue', 'css'] }
];
// Verificar si al menos un miembro tiene habilidades en React
const hasReactDeveloper = team.some(member =>
member.skills.includes('react')
);
// Encontrar miembros que conocen JavaScript y filtrar sus nombres
const javascriptDevs = team
.filter(member => member.skills.includes('javascript'))
.map(member => member.name);
console.log(hasReactDeveloper); // true
console.log(javascriptDevs); // ['Alice', 'Charlie']
Patrones avanzados con flatMap()
El método flatMap()
combina map()
y flat()
, permitiendo transformar y aplanar estructuras anidadas:
const departments = [
{ name: 'Engineering', employees: [
{ name: 'Alice', role: 'Frontend' },
{ name: 'Bob', role: 'Backend' }
]},
{ name: 'Marketing', employees: [
{ name: 'Charlie', role: 'Content' }
]},
{ name: 'HR', employees: [] }
];
// Obtener todos los empleados de ingeniería
const engineeringEmployees = departments
.find(dept => dept.name === 'Engineering')
?.employees || [];
// Obtener todos los empleados de todos los departamentos
const allEmployees = departments
.flatMap(dept => dept.employees)
.map(emp => `${emp.name} (${emp.role})`);
console.log(allEmployees);
// ['Alice (Frontend)', 'Bob (Backend)', 'Charlie (Content)']
Composición funcional con filter() y find()
Podemos crear funciones de utilidad que compongan operaciones de filtrado y búsqueda:
// Función para filtrar y luego encontrar un elemento
const filterAndFind = (array, filterFn, findFn) =>
array.filter(filterFn).find(findFn);
// Función para encontrar y luego filtrar elementos relacionados
const findAndFilterRelated = (array, findFn, relationFn) => {
const found = array.find(findFn);
return found ? array.filter(item => relationFn(item, found)) : [];
};
// Ejemplo de uso
const products = [
{ id: 1, category: 'electronics', price: 1200, brand: 'Apple' },
{ id: 2, category: 'electronics', price: 800, brand: 'Samsung' },
{ id: 3, category: 'books', price: 20, brand: null },
{ id: 4, category: 'electronics', price: 600, brand: 'Samsung' }
];
// Encontrar el primer producto Samsung de más de 700€
const expensiveSamsung = filterAndFind(
products,
p => p.brand === 'Samsung',
p => p.price > 700
);
// Encontrar productos similares al producto con id 2
const similarProducts = findAndFilterRelated(
products,
p => p.id === 2,
(item, found) => item.id !== found.id && item.brand === found.brand
);
console.log(similarProducts);
// [{ id: 4, category: 'electronics', price: 600, brand: 'Samsung' }]
Integración con async/await
Para operaciones asíncronas, podemos combinar filter()
y find()
con Promise.all()
y async/await
:
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' }
];
// Función asíncrona para obtener permisos
const fetchUserPermissions = async (userId) => {
// Simulación de llamada a API
const permissions = {
1: ['read', 'write'],
2: ['read'],
3: ['read', 'write', 'admin']
};
return new Promise(resolve => {
setTimeout(() => resolve(permissions[userId] || []), 100);
});
};
// Encontrar usuarios con permisos de administrador
const findAdmins = async (users) => {
// Obtener permisos para todos los usuarios
const usersWithPermissions = await Promise.all(
users.map(async user => ({
...user,
permissions: await fetchUserPermissions(user.id)
}))
);
// Filtrar usuarios administradores
return usersWithPermissions.filter(user =>
user.permissions.includes('admin')
);
};
// Uso
findAdmins(users).then(admins => {
console.log(admins); // [{ id: 3, name: 'Charlie', permissions: [...] }]
});
La integración de filter()
y find()
con otros métodos funcionales crea un ecosistema coherente para el procesamiento de datos, permitiendo escribir código más declarativo, mantenible y expresivo que refleja claramente la intención del desarrollador.
Ejercicios de esta lección Filtrado con filter() y find()
Evalúa tus conocimientos de esta lección Filtrado con filter() y find() con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
Funciones flecha
Polimorfismo
Array
Transformación con map()
Gestor de tareas con JavaScript
Manipulación DOM
Funciones
Funciones flecha
Async / Await
Creación y uso de variables
Excepciones
Promises
Funciones cierre (closure)
Herencia
Herencia
Estructuras de control
Selección de elementos DOM
Modificación de elementos DOM
Filtrado con filter() y find()
Funciones cierre (closure)
Funciones
Mapas con Map
Reducción con reduce()
Callbacks
Manipulación DOM
Promises
Async / Await
Eventos del DOM
Async / Await
Promises
Filtrado con filter() y find()
Callbacks
Creación de clases y objetos Restaurante
Reducción con reduce()
Filtrado con filter() y find()
Reducción con reduce()
Conjuntos con Set
Herencia de clases
Eventos del DOM
Clases y objetos
Modificación de elementos DOM
Mapas con Map
Introducción a JavaScript
Funciones
Tipos de datos
Clases y objetos
Array
Conjuntos con Set
Array
Encapsulación
Clases y objetos
Uso de operadores
Uso de operadores
Estructuras de control
Excepciones
Transformación con map()
Funciones flecha
Selección de elementos DOM
Encapsulación
Mapas con Map
Creación y uso de variables
Polimorfismo
Tipos de datos
Estructuras de control
Todas las lecciones de JavaScript
Accede a todas las lecciones de JavaScript y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Introducción A Javascript
Introducción Y Entorno
Tipos De Datos
Sintaxis
Variables
Sintaxis
Operadores
Sintaxis
Estructuras De Control
Sintaxis
Funciones
Sintaxis
Funciones Cierre (Closure)
Sintaxis
Arrays Y Métodos
Estructuras De Datos
Conjuntos Con Set
Estructuras De Datos
Mapas Con Map
Estructuras De Datos
Funciones Flecha
Programación Funcional
Filtrado Con Filter() Y Find()
Programación Funcional
Transformación Con Map()
Programación Funcional
Reducción Con Reduce()
Programación Funcional
Clases Y Objetos
Programación Orientada A Objetos
Excepciones
Programación Orientada A Objetos
Encapsulación
Programación Orientada A Objetos
Herencia
Programación Orientada A Objetos
Polimorfismo
Programación Orientada A Objetos
Manipulación Dom
Dom
Selección De Elementos Dom
Dom
Modificación De Elementos Dom
Dom
Eventos Del Dom
Dom
Callbacks
Programación Asíncrona
Promises
Programación Asíncrona
Async / Await
Programación Asíncrona
Certificados de superación de JavaScript
Supera todos los ejercicios de programación del curso de JavaScript y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender el uso y funcionamiento de los métodos
filter()
yfind()
en JavaScript. - Aprender a utilizar
filter()
para crear un nuevo array con elementos filtrados que cumplan una condición dada. - Aprender a utilizar
find()
para obtener el primer elemento que cumpla una condición especificada. - Conocer la sintaxis y uso de funciones flecha como argumentos para
filter()
yfind()
para hacer el código más conciso y fácil de leer. - Familiarizarse con los parámetros que pueden recibirse en las funciones de llamada (callbacks) de
filter()
yfind()
, como el elemento actual del array, el índice y el array en sí, y cómo pueden utilizarse para escribir funciones más avanzadas.