Estoy tratando de crear una función de búsqueda/filtro que permita a los usuarios filtrar una matriz de objetos JS que devuelve una matriz poblada con datos que coinciden con la consulta de búsqueda.
Deseo poder buscar múltiples propiedades en una consulta, por ejemplo; si busco HKG devolvería los 3 objetos, pero si busco HKG 12345 devolvería el primer objeto de la matriz.
Otro ejemplo sería si tuviera que buscar 8 , devolvería los primeros 2 objetos en la matriz de la propiedad sumOfContainers que coinciden con la consulta, pero si buscara 8 SAV , devolvería solo el primer objeto.
results = []; objects = [ {laneId:"12345", lane:"HKG-SAV", equipmentType:"20'STD", sumOfContainers: "8", baseline:"$1234", new:"$1234", newSaving:"$1234"}, {laneId:"12346", lane:"HKG-FRA", equipmentType:"20'STD", sumOfContainers: "8", baseline:"$1234", new:"$1234", newSaving:"$1234"}, {laneId:"12347", lane:"HKG-LAX", equipmentType:"20'STD", sumOfContainers: "9", baseline:"$1234", new:"$1234", newSaving:"$1234"}, ]; const Search = (toSearch) => { for(var i=0; i<objects.length; i++) { for(key in objects[i]) { if(objects[i][key].indexOf(toSearch)!=-1) { results.push(objects[i]); } } } }El problema con mi intento es que devolverá datos duplicados. Me he encontrado con muchas publicaciones en línea, pero tengo dificultades para encontrar publicaciones que busquen un resultado similar.
Estoy tratando de lograr esto con JavaScript nativo.
Algunos asuntos:
Los duplicados se agregan porque después de agregar un objeto, sigues buscando más coincidencias en el mismo objeto. Entonces, si hay alguna otra clave que coincida, el mismo objeto se agregará dos veces
Cuando la búsqueda incluye un espacio, su descripción dice que desea tratarlo como un separador de múltiples términos de búsqueda, pero su código nunca divide el argumento de búsqueda de esa manera.
No hay declaración de return en su función
La variable clave no se declara con var , let o const
Sugeriría resolver esto con filter : esto garantiza que no obtendrá duplicados. Luego requiere que todos los términos de búsqueda tengan una coincidencia: para esto puede usar split and every . Luego requiere que haya al menos una clave que coincida con un término de búsqueda: para esto puede usar some :
No nombre su función de búsqueda con PascalCase, sino con camelCase (así que search en lugar de Search ). La práctica común es que PascalCase está reservado para nombres de clase/constructor.
const search = toSearch => { let terms = toSearch.split(" "); return objects.filter(object => terms.every(term => Object.values(object).some(value => value.includes(term) ) ) ); }Se me ocurrió una forma bastante pésima de lograr las condiciones en la pregunta. Si alguien puede hacer que este código sea más óptimo, sería fantástico.
const search = () => { let toSearch = document.getElementById("search").value; let lanes = this.objects; let result = []; const filters = toSearch.split(" "); for(let i = 0; i <lanes.length; i++) { let search = ""; let isMatched = true; for(let key in lanes[i]) { search += lanes[i][key] + " "; } filters.forEach(filter => { if(search.indexOf(filter) == -1) { isMatched = false; break; } }); if(isMatched) { result.push(lanes[i]); } } return result; }Si no te importa lodash :
const _ = require('lodash'); const objects = [ {laneId:"12345", lane:"HKG-SAV", equipmentType:"20'STD", sumOfContainers: "8", baseline:"$1234", new:"$1234", newSaving:"$1234"}, {laneId:"12346", lane:"HKG-FRA", equipmentType:"20'STD", sumOfContainers: "8", baseline:"$1234", new:"$1234", newSaving:"$1234"}, {laneId:"12347", lane:"HKG-LAX", equipmentType:"20'STD", sumOfContainers: "9", baseline:"$1234", new:"$1234", newSaving:"$1234"}, ]; const mySearch = (arr, text) => { const includesValue = (word, obj) => _.some(obj, (value) => _.includes(value, word)); const words = _.words(text); return arr .filter((obj) => words.every((word) => includesValue(word, obj) ) ); }; console.log(mySearch(objects, 'HKG 12345')); // [{laneId: '12345', lane: 'HKG-SAV', equipmentType: "20'STD", sumOfContainers: '8', baseline: '$1234', new: '$1234', newSaving: '$1234' }] console.log(mySearch(objects, '8')); // [ // {laneId:"12345", lane:"HKG-SAV", equipmentType:"20'STD", sumOfContainers: "8", baseline:"$1234", new:"$1234", newSaving:"$1234"}, // {laneId:"12346", lane:"HKG-FRA", equipmentType:"20'STD", sumOfContainers: "8", baseline:"$1234", new:"$1234", newSaving:"$1234"}, // ] console.log(mySearch(objects, '8 SAV')); // [{laneId: '12345', lane: 'HKG-SAV', equipmentType: "20'STD", sumOfContainers: '8', baseline: '$1234', new: '$1234', newSaving: '$1234' }]