Tengo una variedad de products que a su vez tienen una variedad de categories . Quiero extraer valores distintos de la propiedad de type en el objeto de category .
Tanto Lodash como las versiones nativas a continuación hacen el trabajo.
Quiero hacer una función genérica que tome el camino de la propiedad y devuelva valores únicos.
Esencialmente, estoy viendo algo conciso como map(products, property("categories[].type") pero aquí están las versiones más largas
import { compact, flatten, map, property, uniq } from "lodash"; export const getAllTypes1 = (products) => { return uniq( compact(map(flatten(map(products, property("categories"))), "type")) ); }; export const getAllTypes2 = (products) => { const types = []; products.forEach((product) => { product.categories.forEach((category) => { if (!types.some((t) => t === category.type)) { types.push(category.type); } }); }); return types; };datos de ejemplo
const product1 = { name: 'Wilson Orange', price: 72.50, categories: [{ type: 'flash sale', discountable: false, },{ type: 'tennis', discountable: true, }] }; const product2 = { name: 'Babolat Green', price: 65.50, categories: [{ type: 'tennis', discountable: true, }] }; const products = [product1, product2];Resultado
const result = getAllTypes2(products); console.log(result); // ["flash sale", "tennis"]Aquí hay un ejemplo de trabajo
Aquí hay una función Vanilla JS que toma el camino sin necesidad de [] y verifica automáticamente las matrices donde sea que encuentre una.
Cómo funciona es:
Set vacío para eliminar fácilmente los duplicadospropsrecurse(currObj, props) que:currObj es una matriz y si lo es: a. Se recurre de nuevo con los valores de la matriz como currObj b. Use los mismos props ya que no verificamos un objeto en el caminocurrObj[currProp] , y los accesorios restantes const product1 = { name: 'Wilson Orange', price: 72.5, categories: [ { type: 'flash sale', discountable: false, }, { type: 'tennis', discountable: true, }, ], }; const product2 = { name: 'Babolat Green', price: 65.5, categories: [ { type: 'tennis', discountable: true, }, ], }; const products = [product1, product2]; function getProperties(array, path) { const props = path.split('.'); const values = new Set(); function recurse(currObj, props) { const currProp = props[0] const nextProps = props.slice(1); if (Array.isArray(currObj)) { for (let val of currObj) { recurse(val, props); } return } if (nextProps.length === 0) { values.add(currObj[currProp]) } else { recurse(currObj[currProp], nextProps) } } recurse(array, props); return [...values]; } console.log(getProperties(products,'categories.type')) console.log(getProperties(products,'price')) console.log(getProperties(products,'name'))No es una cadena de ruta de propiedad, pero es bastante breve y expresiva:
const pipe = (...fs) => fs.reduceRight( (next, f) => x => f(x, next), x => x, ); const getAllTypes = pipe( (x, next) => [...new Set(x.flatMap(next))], (x, next) => x.categories.map(next), (x) => x.type, ); // equivalent to // const getAllTypes = // x => [...new Set(x.flatMap(y => y.categories.map(z => z.type)))]; const products = [{ name: 'Wilson Orange', price: 72.50, categories: [{ type: 'flash sale', discountable: false, }, { type: 'tennis', discountable: true, }] }, { name: 'Babolat Green', price: 65.50, categories: [{ type: 'tennis', discountable: true, }] }]; console.log(getAllTypes(products)); El parámetro x => x permite llamar a la pipe sin ningún argumento y devolver la función de identidad. También permite que el último argumento de función de la pipe acepte un next parámetro por consistencia, es decir, (x, next) => next(x.type) habría sido equivalente a (x) => x.type .
Referencia: