J'ai cet objet JavaScript:
_.get(object, 'categories[].items[].image') // => ["path/to/file-1.png", "path/to/file-2.png", "path/to/file-3.png", "path/to/file-4.png", "path/to/file-5.png", "path/to/file-6.png"]
J'ai pu sélectionner un seul élément en utilisant la méthode _.get de _.get
.
_.get(object, 'categories[0].items[0].image') // => "path/to/file-1.png"
Mais j'ai besoin d'un tableau avec toutes les occurrences, pas seulement à partir de la position 0. Quelque chose comme ceci:
const object = { categories: [ { title: 'Category 1', items: [ { title: 'Item 1', image: 'path/to/file-1.png' }, { title: 'Item 2', image: 'path/to/file-2.png' }, { title: 'Item 3', image: 'path/to/file-3.png' } ] }, { title: 'Category 2', items: [ { title: 'Item 4', image: 'path/to/file-4.png' }, { title: 'Item 5', image: 'path/to/file-5.png' }, { title: 'Item 6', image: 'path/to/file-6.png' } ] } ] }
Est-il possible de le faire avec Lodash?
Si ce n'est pas possible, avez-vous une idée de la façon de le mettre en œuvre?
EDIT: Je recherche quelque chose comme _.get
de Lodash, où je peux fournir le "schéma de recherche" (chemin) sous forme de chaîne. Évidemment, je sais comment résoudre ce problème avec la map
, la reduce
, etc.
4 Réponses :
C'est assez facile à faire avec flatMap
, aucune bibliothèque requise:
const object = { categories: [ { title: 'Category 1', items: [ { title: 'Item 1', image: 'path/to/file-1.png' }, { title: 'Item 2', image: 'path/to/file-2.png' }, { title: 'Item 3', image: 'path/to/file-3.png' } ] }, { title: 'Category 2', items: [ { title: 'Item 4', image: 'path/to/file-4.png' }, { title: 'Item 5', image: 'path/to/file-5.png' }, { title: 'Item 6', image: 'path/to/file-6.png' } ] } ] }; const images = object.categories.reduce((a, { items }) => { items.forEach(({ image }) => { a.push(image); }); return a; }, []); console.log(images);
Ou, avec reduce
:
const object = { categories: [ { title: 'Category 1', items: [ { title: 'Item 1', image: 'path/to/file-1.png' }, { title: 'Item 2', image: 'path/to/file-2.png' }, { title: 'Item 3', image: 'path/to/file-3.png' } ] }, { title: 'Category 2', items: [ { title: 'Item 4', image: 'path/to/file-4.png' }, { title: 'Item 5', image: 'path/to/file-5.png' }, { title: 'Item 6', image: 'path/to/file-6.png' } ] } ] }; const images = object.categories.flatMap(({ items }) => items.map(({ image }) => image)); console.log(images);
Oui, je sais comment le faire en utilisant des boucles / fonctions ... J'ai oublié d'être clair que j'ai besoin de quelque chose comme _.get
, où je peux fournir le "schéma de recherche" sous forme de chaîne.
Voici mon implémentation qui peut gérer le chemin []
:
_.map(object.categories[0].items, o => _.get(o, 'image')) // if categories[0].items is not always there, just use another get: _.map(_.get(object, 'categories[0].items'), o => _.get(o, 'image'))
édité avant:
Parce que vous devez obtenir le tableau d' images
, la map
pourrait vous aider. En voici une simple:
const object = { categories: [ { title: "Category 1", items: [ { title: "Item 1", image: "path/to/file-1.png" }, { title: "Item 2", image: "path/to/file-2.png" }, { title: "Item 3", image: "path/to/file-3.png" } ] }, { title: "Category 2", items: [ { title: "Item 4", image: "path/to/file-4.png" }, { title: "Item 5", image: "path/to/file-5.png" }, { title: "Item 6", image: "path/to/file-6.png" } ] } ] }; const object2 = { categories: { title: "Category 1" } }; function flatGet(object, path) { const pathArray = path.split("."); while (pathArray.length > 0) { let pos = pathArray.shift(); if (pos.includes("[]")) { pos = pos.slice(0, -2); } if (Array.isArray(object)) { object = object.reduce((acc, cur) => acc.concat(cur[pos]), []); } else { object = object[pos]; } } return object; } var res = flatGet(object, "categories[].items[].image"); // ["path/to/file-1.png", ...] var res2 = flatGet(object2, "categories.title"); // "Category 1"
Voici mon implémentation d'une fonction flatGet
qui peut gérer des tableaux:
const flatGet = (object, path) => { const p = path.match(/[^.\[\]]+/g) const getItem = (item, [current, ...path]) => { if(current === undefined) return item if(typeof item !== 'object') return undefined if(Array.isArray(item)) return item.flatMap(o => getItem(o[current], path)) return getItem(item[current], path) } return getItem(object, p) } const object = {"categories":[{"title":"Category 1","items":[{"title":"Item 1","image":"path/to/file-1.png"},{"title":"Item 2","image":"path/to/file-2.png"},{"title":"Item 3","image":"path/to/file-3.png"}]},{"title":"Category 2","items":[{"title":"Item 4","image":"path/to/file-4.png"},{"title":"Item 5","image":"path/to/file-5.png"},{"title":"Item 6","image":"path/to/file-6.png"}]}]} var result = flatGet(object, 'categories.items.image') console.log(result)
Merci, c'était exactement ce dont j'avais besoin.
Nous utilisons maintenant l' analyse d' objets pour ces types de requêtes. C'est assez puissant (une fois que vous en avez la tête) et assez facile à utiliser pour les choses de base. Voici comment vous pourriez résoudre votre problème
const objectScan = require('object-scan'); const object = { categories: [ { title: 'Category 1', items: [ { title: 'Item 1', image: 'path/to/file-1.png' }, { title: 'Item 2', image: 'path/to/file-2.png' }, { title: 'Item 3', image: 'path/to/file-3.png' } ] }, { title: 'Category 2', items: [ { title: 'Item 4', image: 'path/to/file-4.png' }, { title: 'Item 5', image: 'path/to/file-5.png' }, { title: 'Item 6', image: 'path/to/file-6.png' } ] } ] }; const r = objectScan(['categories[*].items[*].image'], { rtn: 'value' })(object); console.log(r); // => [ 'path/to/file-6.png', 'path/to/file-5.png', 'path/to/file-4.png', // 'path/to/file-3.png', 'path/to/file-2.png', 'path/to/file-1.png' ]