基于Property合并两个数组

时间:2017-10-19 16:17:40

标签: javascript lodash

我有两个数组:一个包含类别,第二个包含项目。

我想使用lodash将所有项目项合并到正确的类别数组中。但是,我确实有一个问题。由于这可以通过双foreach循环完成,有没有理由使用lodash?

数组1(类别):

"categories": [
    {
        "id": 1,
        "name": "cat_1",
        "items": []
    },
    {
        "id": 11,
        "name": "cat_2",
        "items": []
    },
    {
        "id": 61,
        "name": "cat_3",
        "items": []
    }
]

数组2(包含项目):

[ 
    { 
        id: 15,
        name: 'some_item',
        category_id: 1,
        category_name: 'cat_1',
    },
    { 
        id: 112,
        name: 'some_item',
        category_id: 11,
        category_name: 'cat_2',
    },
    { 
        id: 235,
        name: 'some_item',
        category_id: 11,
        category_name: 'cat_2',
    },

]

期望的对象看起来:

"categories": 
    [
        {
            "id": 1,
            "name": "cat_1",
            "items": [
                { 
                    id: 15,
                    name: 'some_item',
                    category_id: 1,
                    category_name: 'cat_1',
                }
            ]
        },
        {
            "id": 11,
            "name": "cat_2",
            "items": [
                { 
                    id: 112,
                    name: 'some_item',
                    category_id: 11,
                    category_name: 'cat_2',
                },
                { 
                    id: 235,
                    name: 'some_item',
                    category_id: 11,
                    category_name: 'cat_2',
                }
            ]
        },
        {
            "id": 61,
            "name": "cat_3",
            "items": []
        }
    ]

4 个答案:

答案 0 :(得分:4)

这就是你用普通ES5做的方法:

const categories = [{id:1,name:"cat_1",items:[]},{id:11,name:"cat_2",items:[]},{id:61,name:"cat_3",items:[]}]
const items = [{id:15,name:"some_item",category_id:1,category_name:"cat_1"},{id:112,name:"some_item",category_id:11,category_name:"cat_2"},{id:235,name:"some_item",category_id:11,category_name:"cat_2"}];

const result =
  categories.map(c => ({ ...c, items: items.filter(i => i.category_id === c.id) }));
  
console.log(result);

Javascript是一种非常特殊的语言,因为它的历史。它起初是一种非常简陋的语言,功能很少,虽然它已经发展,但并非所有浏览器都支持它的所有功能。

这导致了像lodash,underscore,inmutable.js和jquery这样的库的出现,这填补了Javascript标准库中的空白。

如您所见,现在JS有非常方便的抽象,例如eachmapfindfilterreduce,它们是普遍理解的概念跨语言。与使用for循环编写低级过程代码相比,这使代码更容易理解。

作为一个颜色注释,我开始使用ruby进行编程,ruby以standard library rich in collection abstractions而闻名。结果,直到最近,我才注意到语言中有for循环,即使它们是实现更高级别抽象的必要条件。

答案 1 :(得分:1)

我从未使用过lodash,但你是对的,这可以通过foreach循环轻松完成。甚至不是一个双foreach循环,一个'.find'或'.filter'

(a)循环浏览每个项目并使用array.find查找相应的类别,并将该项目输入到类别中

(b)循环浏览每个类别并使用array.filter查找相应的项目,并将这些项目输入每个类别。

这是一个选项:

(()=>{
  const categories = [{
      "id": 1,
      "name": "cat_1",
      "items": []
    },
    {
      "id": 11,
      "name": "cat_2",
      "items": []
    },
    {
      "id": 61,
      "name": "cat_3",
      "items": []
    }]

  const items = [{ 
      id: 15,
      name: 'some_item',
      category_id: 1,
      category_name: 'cat_1',
    },
    { 
      id: 112,
      name: 'some_item',
      category_id: 11,
      category_name: 'cat_2',
    },
    { 
      id: 235,
      name: 'some_item',
      category_id: 11,
      category_name: 'cat_2',
    }]

  categories.forEach((cat) => {
    cat.items = items.filter((item) => item.category_id === cat.id);
  })
})()

答案 2 :(得分:0)

您可以使用lodash _.keyBy()按类别ID对项目进行分组,然后使用Array#map循环分类,并创建新的类别对象,其中的项目来自itemsByCategory:< / p>

&#13;
&#13;
const categories = [{"id":1,"name":"cat_1","items":[]},{"id":11,"name":"cat_2","items":[]},{"id":61,"name":"cat_3","items":[]}];

const items = [{"id":15,"name":"some_item","category_id":1,"category_name":"cat_1"},{"id":112,"name":"some_item","category_id":11,"category_name":"cat_2"},{"id":235,"name":"some_item","category_id":11,"category_name":"cat_2"}];

const itemsByCategory = _.groupBy(items, 'category_id');
const categoriesWithItems = categories.map(({ id, name, items }) => ({
  id,
  name,
  items: items.concat(itemsByCategory[id])
}));

console.log(categoriesWithItems);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
&#13;
&#13;
&#13;

正如您所看到的,我使用的唯一方法是_.keyBy(),我们可以将其替换为Array#reduce

&#13;
&#13;
const categories = [{"id":1,"name":"cat_1","items":[]},{"id":11,"name":"cat_2","items":[]},{"id":61,"name":"cat_3","items":[]}];

const items = [{"id":15,"name":"some_item","category_id":1,"category_name":"cat_1"},{"id":112,"name":"some_item","category_id":11,"category_name":"cat_2"},{"id":235,"name":"some_item","category_id":11,"category_name":"cat_2"}];

const itemsByCategory = items.reduce((r, item) => {
  r[item.category_id] = item;
  
  return r;
}, {});

const categoriesWithItems = categories.map(({ id, name, items }) => ({
  id,
  name,
  items: items.concat(itemsByCategory[id])
}));

console.log(categoriesWithItems);
&#13;
&#13;
&#13;

因此,使用lodash主要是方便的。由于lodash是用JS编写的,你可以使用JS创建lodash做的任何东西(而ES6让生活变得更轻松),并且它可以节省一些包大小。但是,lodash确实可以节省大量手写的纯测试代码,从而重新发明轮子。我建议使用lodash-es而不是lodash,因为es版本是模块化的,你可以导入你需要的东西。这平衡了易用性和捆绑尺寸。

答案 3 :(得分:0)

您可以为类别选择Map,然后迭代项目以推送到相应的类别。

&#13;
&#13;
var object = { categories: [{ id: 1, name: "cat_1", items: [] }, { id: 11, name: "cat_2", items: [] }, { id: 61, name: "cat_3", items: [] }] },
    items = [{ id: 15, name: 'some_item', category_id: 1, category_name: 'cat_1', }, { id: 112, name: 'some_item', category_id: 11, category_name: 'cat_2', }, { id: 235, name: 'some_item', category_id: 11, category_name: 'cat_2', }],
    map = new Map(object.categories.map(category => [category.id, category.items]));

items.forEach(item => map.get(item.category_id).push(item));

console.log(object);
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
&#13;
&#13;