/** * Utility to perform fuzzy search in an array of objects, ignoring accents, case, and word order. */ /** * Normalize a string by removing accents and converting to lowercase. * @param str Input string. * @returns Normalized string. */ function normalizeString(str: string): string { return str .normalize("NFD") // Decomposes accented characters .replace(/\p{Diacritic}/gu, "") // Removes diacritical marks (accents) .toLowerCase(); // Converts to lowercase } /** * Extracts a set of normalized words from a given text. * @param text Input string. * @returns A Set containing unique normalized words. */ function getNormalizedWords(text: string): Set { return new Set(normalizeString(text).split(/\s+/)); } /** * Filters an array of objects based on a search query. * @param data The dataset to filter (array of objects). * @param keys The object properties to search within. * @param query The search query. * @returns Filtered array of matching objects. */ function fuzzySearch>( data: T[], keys: (keyof T)[], query: string ): T[] { if (!query.trim()) return data; const queryWords = getNormalizedWords(query); return data.filter((item) => keys.some((key) => { const value = item[key]; if (typeof value !== "string") return false; const textWords = getNormalizedWords(value); return [...queryWords].every((qWord) => [...textWords].some((tWord) => tWord.includes(qWord)) ); }) ); } // Example Usage const dataset = [ { id: 1, name: "El gato negro en el techo" }, { id: 2, name: "Una casa blanca con jardín" }, { id: 3, name: "El perro marrón corre en el parque" }, { id: 4, name: "Negro el gato subió al techo" }, ]; const query = "negro techo gat"; // Searching for: "negro techo gato" const results = fuzzySearch(dataset, ["name"], query); console.log(results);