Guía de Filtrado Difuso
Ejemplos
¿Quieres saltar a la implementación? Echa un vistazo a estos ejemplos:
API
Guía de Filtrado Difuso
El filtrado difuso es una técnica que te permite filtrar datos basándose en coincidencias aproximadas. Esto puede ser útil cuando quieres buscar datos que son similares a un valor dado, en lugar de una coincidencia exacta.
Puedes implementar un filtrado difuso del lado del cliente definiendo una función de filtro personalizada. Esta función debe tomar la fila, el columnId y el valor del filtro, y devolver un booleano que indique si la fila debe incluirse en los datos filtrados.
El filtrado difuso se utiliza principalmente con el filtrado global, pero también puedes aplicarlo a columnas individuales. Discutiremos cómo implementar el filtrado difuso para ambos casos.
Nota: Deberás instalar la librería
@tanstack/match-sorter-utilspara usar el filtrado difuso. TanStack Match Sorter Utils es un "fork" de match-sorter de Kent C. Dodds. Se bifurcó para funcionar mejor con el enfoque de filtrado fila por fila de TanStack Table.
El uso de las librerías match-sorter es opcional, pero la librería TanStack Match Sorter Utils proporciona una excelente manera tanto de realizar filtrado difuso como de ordenar por la información de rango que devuelve, de modo que las filas puedan ordenarse por sus coincidencias más cercanas a la consulta de búsqueda.
Definiendo una Función de Filtro Difuso Personalizada
Aquí tienes un ejemplo de una función de filtro difuso personalizada:
import { rankItem } from "@tanstack/match-sorter-utils";
import { FilterFn } from "@tanstack/table";
const fuzzyFilter: FilterFn<any> = (row, columnId, value, addMeta) => {
// Clasificar el elemento
const itemRank = rankItem(row.getValue(columnId), value);
// Almacenar la información de itemRank
addMeta({ itemRank });
// Devolver si el elemento debe ser filtrado (incluido/excluido)
return itemRank.passed;
};
En esta función, estamos utilizando la función rankItem de la librería @tanstack/match-sorter-utils para clasificar el elemento. Luego almacenamos la información de clasificación en los metadatos de la fila y devolvemos si el elemento pasó los criterios de clasificación.
Usando el Filtrado Difuso con el Filtrado Global
Para usar el filtrado difuso con el filtrado global, puedes especificar la función de filtro difuso en la opción globalFilterFn de la instancia de la tabla:
const table = useReactTable({
// o la función equivalente de tu framework
columns,
data,
filterFns: {
fuzzy: fuzzyFilter, // definir como una función de filtro que puede ser usada en las definiciones de columna
},
globalFilterFn: "fuzzy", // aplicar filtro difuso al filtro global (caso de uso más común para el filtro difuso)
getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(), // filtrado del lado del cliente
getSortedRowModel: getSortedRowModel(), // se necesita ordenación del lado del cliente si también quieres usar la ordenación.
});
Usando el Filtrado Difuso con el Filtrado por Columna
Para usar el filtrado difuso con el filtrado por columna, primero debes definir la función de filtro difuso en la opción filterFns de la instancia de la tabla. Luego puedes especificar la función de filtro difuso en la opción filterFn de la definición de la columna:
const column = [
{
accessorFn: (row) => `${row.firstName} ${row.lastName}`,
id: "fullName",
header: "Full Name",
cell: (info) => info.getValue(),
filterFn: "fuzzy", // usando nuestra función de filtro difuso personalizada
},
// otras columnas...
];
En este ejemplo, estamos aplicando el filtro difuso a una columna que combina los campos firstName y lastName de los datos.
Ordenación con Filtrado Difuso
Cuando se utiliza el filtrado difuso con el filtrado por columna, también podrías querer ordenar los datos basándote en la información de clasificación. Puedes hacer esto definiendo una función de ordenación personalizada:
import { compareItems } from "@tanstack/match-sorter-utils";
import { sortingFns } from "@tanstack/table";
const fuzzySort: SortingFn<any> = (rowA, rowB, columnId) => {
let dir = 0;
// Solo ordenar por rango si la columna tiene información de clasificación
if (rowA.columnFiltersMeta[columnId]) {
dir = compareItems(
rowA.columnFiltersMeta[columnId]?.itemRank!,
rowB.columnFiltersMeta[columnId]?.itemRank!,
);
}
// Proporcionar un respaldo alfanumérico para cuando los rangos de los elementos sean iguales
return dir === 0 ? sortingFns.alphanumeric(rowA, rowB, columnId) : dir;
};
En esta función, estamos comparando la información de clasificación de las dos filas. Si los rangos son iguales, recurrimos a la ordenación alfanumérica.
Luego puedes especificar esta función de ordenación en la opción sortFn de la definición de la columna:
{
accessorFn: row => `${row.firstName} ${row.lastName}`,
id: 'fullName',
header: 'Full Name',
cell: info => info.getValue(),
filterFn: 'fuzzy', // usando nuestra función de filtro difuso personalizada
sortFn: 'fuzzySort', // usando nuestra función de ordenación difusa personalizada
}