使用Lodash _.get返回多个元素?

时间:2019-05-30 06:28:34

标签: javascript lodash

我有这个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' }
      ]
    }
  ]
}

我只能使用Lodash的_.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做到这一点?

如果不可能,您是否知道如何实施?

编辑:我正在从Lodash寻找类似_.get的东西,我可以在其中提供“搜索模式”(路径)作为字符串。显然,我知道如何使用mapreduce等来解决这个问题。

4 个答案:

答案 0 :(得分:2)

使用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 :(得分:1)

这是我对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)

答案 2 :(得分:0)

我们现在对这些类型的查询使用object-scan。它非常强大(一旦您将头围起来),并且足够容易用于基本内容。这是解决问题的方法

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

答案 3 :(得分:-1)

这是我的实现,可以处理[]路径:

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