¿Cómo filtrar datos de una matriz de matriz?
los pls encuentran la explicación en el ejemplo dado a continuación.
Debemos usar startnumber y endnumber en la consulta de datos.
const data = [ { "name": "x", "points": [ [100, 50, 1], //[number, value, bit] [150, 51, 0], [170, 52, 1], [200, 53, 0] ] }, { "name": "y", "points": [ [60, 50, 1], [100, 5, 1], [150, 6, 0], [170, 7, 1], [200, 53, 1] ] }, { "name": "z", "points": [ [300, 50, 1], [350, 51, 0], [370, 52, 1], [400, 53, 1] ] } ] // want to find the records with name equal to x & y and number between 100 to 170 const names = ["x", "y"]; const startnumber = 100; const endnumber = 170; const finalResult= []; for(const n of names){ console.log('name', n); console.log('startnumber', startnumber) console.log('endnuumber', endnumber) const result = data.find(x=>x.name === n) // how to use startnumber and endnumber here in above line/query ? OR some other elegant solution is required if(result){ finalResult.push('result', result); } } if(finalResult.length){ console.log(finalResult); } [ { "name": "x", "points": [ [100, 50, 1], [150, 51, 0], [170, 52, 1], ] }, { "name": "y", "points": [ [100, 5, 1], [150, 6, 0], [170, 7, 1], ] } ]const results = data.filter(elem => !!names.find(name => name == elem.name))Explicación:
data.filter aplica la devolución de llamada a cada elemento de la matriz datanames.find aplica la devolución de llamada a cada elemento de la matriz de names para encontrar una coincidencia.!! se usa porque find devuelve un elemento, entonces !! provoca una doble negación que lo convierte en un valor booleano, el retorno esperado de la devolución de llamada de find (en realidad, no es estrictamente necesario, ya que la devolución de find undefined se convertiría en falso), pero aclara la intención.data que tienen propiedades de nombres que coinciden con los valores en names . const data = [ { "name": "x", "points": [ [100, 50, 1], //[number, value, bit] [150, 51, 0], [170, 52, 1], [200, 53, 0] ] }, { "name": "y", "points": [ [60, 50, 1], [100, 5, 1], [150, 6, 0], [170, 7, 1], [200, 53, 1] ] }, { "name": "y", "points": [ [60, 50, 1], [200, 53, 1] ] }, { "name": "z", "points": [ [300, 50, 1], [350, 51, 0], [370, 52, 1], [400, 53, 1] ] } ] // want to find the records with name equal to x & y and number between 100 to 170 const names = ["x", "y"]; const startNumber = 100; const endNumber = 170; const results = data .filter(elem => !!names.find(name => name == elem.name)) .map(elem => { return { name: elem.name, points: elem.points.filter(point => point[0] >= startNumber && point[0] <= endNumber) } }) .filter(elem => elem.points.length > 0) console.log(results)La tarea y las dos estructuras de datos dadas implican un proceso de filtro doble para cada elemento de datos.
names proporcionada adicionalmente).points de cada elemento de datos según si el primer elemento de la matriz de un elemento de points (el valor number ) se encuentra dentro de un determinado rango de números (que se define mediante los valores de número startnumber y endnumber final proporcionados adicionalmente). Por lo tanto, un enfoque viable fue reduce la matriz de data proporcionada por una función reductora que para cada elemento de data se ocupa de las dos tareas anteriores.
El valor inicial de la función reducer será una especie de objeto de configuración y/o colector que presenta...
name (aplicada como una instancia de Map ) para que los elementos de data se procesen explícitamente.startnumber y endnumber como lowerNumber respectivamente upperNumber .result en la que solo se insertan los elementos data que cumplen todos los requisitos. function collectItemsByNameWhichHavePointsInNumberRange(collector, item) { const { nameLookup, lowerNumber, upperNumber, result } = collector; let { name, points } = item; // ... collect items by name ... if (nameLookup.has(name)) { points = points .filter(([number]) => (number >= lowerNumber) && (number <= upperNumber) ); // ... which (actually do) have points (with)in (a) number range. // (according to the above `points` filter result) if (points.length >= 1) { result .push({ ...item, points, }); } } return collector; } const data = [{ name: "x", points: [ //[number, value, bit] [100, 50, 1], [150, 51, 0], [170, 52, 1], [200, 53, 0], ], }, { name: "y", points: [ [60, 50, 1], [100, 5, 1], [150, 6, 0], [170, 7, 1], [200, 53, 1], ], }, { name: "z", points: [ [300, 50, 1], [350, 51, 0], [370, 52, 1], [400, 53, 1], ], }]; const names = ["x", "y"]; const startnumber = 100; const endnumber = 170; const { result } = data .reduce(collectItemsByNameWhichHavePointsInNumberRange, { nameLookup: new Map(names.map(value => [value, value])), lowerNumber: startnumber, upperNumber: endnumber, result: [], }); console.log({ result }); .as-console-wrapper { min-height: 100%!important; top: 0; }La solución más elegante:
const res = data.reduce((acc, curr) => { const { name, points } = curr const filteredPoints = points.filter(p => p[0] >= startNumber && p[0] <= endNumber) return names.includes(name) && filteredPoints.length > 0 ? acc.concat({ name, points: filteredPoints }) : acc }, [])