Вернуть несколько элементов, используя Lodash _.get? - PullRequest
0 голосов
/ 30 мая 2019

У меня есть этот объект JavaScript:

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

Мне удалось выбрать только один элемент, используя метод _.get Лодаша.

_.get(object, 'categories[0].items[0].image')
// => "path/to/file-1.png"

Но мне нужен массив со всеми вхождениямиНе только с позиции 0. Примерно так:

_.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"]

Возможно ли это сделать с помощью Lodash?

Если это невозможно, у вас есть идеи, как это реализовать?

РЕДАКТИРОВАТЬ: Я ищу что-то вроде _.get от Lodash, где я могу предоставить "схему поиска" (путь) в виде строки.Очевидно, я знаю, как решить эту проблему с помощью map, reduce и т. Д.

Ответы [ 3 ]

2 голосов
/ 30 мая 2019

Это довольно легко сделать с flatMap, библиотека не требуется:

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

Или, с 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.reduce((a, { items }) => {
  items.forEach(({ image }) => {
    a.push(image);
  });
  return a;
}, []);
console.log(images);
1 голос
/ 30 мая 2019

Это моя реализация функции flatGet, которая может обрабатывать массивы:

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)
0 голосов
/ 30 мая 2019

Вот моя реализация, которая может обрабатывать [] путь:

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"

отредактировано ранее:

Потому что вам нужно получить массив images, map может помочь с этим. Вот простой:

_.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'))
...