0
votes

Renvoyer plusieurs éléments en utilisant Lodash _.get?

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.


0 commentaires

4 Réponses :


2
votes

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);


1 commentaires

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.



-1
votes

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"


0 commentaires

1
votes

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)


1 commentaires

Merci, c'était exactement ce dont j'avais besoin.



0
votes

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' ]


0 commentaires