[英]Merge & Group Two Javascript array of objects and Group
I have two arrays of objects. 我有两个对象数组。 One array contains list of items, another array contains list of categories.
一个数组包含项目列表,另一个数组包含类别列表。 I want to create a new array based on categoryIds.
我想基于categoryIds创建一个新的数组。 I tried using lodash.
我尝试使用lodash。 But, couldn't get the correct solution.
但是,无法获得正确的解决方案。
I can do this using looping. 我可以使用循环来做到这一点。 But, I am looking for more clean approach.
但是,我正在寻找更干净的方法。
var items = [
{
id: '001',
name: 'item1',
description: 'description of item1',
categoryId: 'cat1'
},
{
id: '002',
name: 'item2',
description: 'description of item2',
categoryId: 'cat2'
},
{
id: '003',
name: 'item3',
description: 'description of item3',
categoryId: 'cat1'
},
{
id: '004',
name: 'item4',
description: 'description of item4'
}
];
var categories = [
{
id: 'cat1',
name: 'Category1'
},
{
id: 'cat2',
name: 'Category2'
}
];
Expected output 预期产量
[
{
categoryId: 'cat1',
name: 'Category1',
items: [
{
id: '001',
name: 'item1',
description: 'description of item1',
categoryId: 'cat1'
},
{
id: '003',
name: 'item3',
description: 'description of item3',
categoryId: 'cat1'
}
]
},
{
categoryId: 'cat2',
name: 'Category2',
items: [
{
id: '002',
name: 'item2',
description: 'description of item2',
categoryId: 'cat2'
}
]
},
{
categoryId: '',
name: '',
items: [
{
id: '004',
name: 'item4',
description: 'description of item4'
}
]
}
]
https://jsfiddle.net/sfpd3ppn/ https://jsfiddle.net/sfpd3ppn/
Thanks for the help 谢谢您的帮助
The following does the trick: 以下是窍门:
var items = [{ id: '001', name: 'item1', description: 'description of item1', categoryId: 'cat1' }, { id: '002', name: 'item2', description: 'description of item2', categoryId: 'cat2' }, { id: '003', name: 'item3', description: 'description of item3', categoryId: 'cat1' }, { id: '004', name: 'item4', description: 'description of item4' } ]; var categories = [ { id: 'cat1', name: 'Category1' }, { id: 'cat2', name: 'Category2' } ]; var output = categories.concat([{id:'',name:''}]).map(function(v) { return { categoryId: v.id, name: v.name, items: items.filter(function(o) { return o.categoryId === v.id || !o.categoryId && !v.id; }) }; }); console.log(output);
I start by using .concat()
to create a new categories array that holds the original categories
items plus an "empty" category. 我首先使用
.concat()
创建一个新的.concat()
数组,该数组包含原始categories
项目以及一个“空”类别。 Then I .map()
that array to return category objects with your desired output structure, each of which has an items
array that is produced by .filter()
ing the original items
array. 然后,我对该数组进行
.map()
返回具有所需输出结构的类别对象,每个类别对象都有一个items
数组,该数组由.filter()
生成原始items
数组产生。
(Note that the items
arrays within the output
contain references to the same objects that were in the original items
input, not copies of them. If you wanted copies you could add another .map()
after the .filter()
.) (请注意,
output
中的items
数组包含对原始items
输入中相同对象的引用, 而不是它们的副本。如果要复制,可以在.filter()
之后添加另一个.map()
.filter()
。)
You can accomplish the desired result using a reduce . 您可以使用reduce来实现所需的结果。 We are going to start with the original
categories
array and reduce the items
array into it. 我们将从原始的
categories
数组开始,并将items
数组减少到其中。
var items = [
{ id: '001', name: 'item1', description: 'description of item1', categoryId: 'cat1' },
{ id: '002', name: 'item2', description: 'description of item2', categoryId: 'cat2' },
{ id: '003', name: 'item3', description: 'description of item3', categoryId: 'cat1' },
{ id: '004', name: 'item4', description: 'description of item4' }
];
var categories = [
{ id: 'cat1', name: 'Category1' },
{ id: 'cat2', name: 'Category2' }
];
// Lets add the empty category at the beginning. This simplifies the logic.
categories.push({ id: '', name: '' });
// This is a function that will return a function to be used as a filter later on
function createFilter (category) {
return function (item) {
return item.id === category;
};
}
var mergedSet = items.reduce(function (previous, current) {
// Get the category ID of the current item, if it doesn't exist set to empty string
var categoryId = current.categoryId || '';
// Find the cateogry that matches the category ID
var category = previous.find(createFilter(categoryId));
// If the items property doesn't exists (we don't have any items), create an empty array
if (!category.items) { category.items = []; }
// Add the item the category
category.items.push(current);
// Return the current value that will be used in the next iteration.
// Note, the initial value of previous will be the intial value of categories.
return previous;
}, categories);
console.log(mergedSet);
/* Output
[
{ id: 'cat1',
name: 'Category1',
items:
[ { id: '001',
name: 'item1',
description: 'description of item1',
categoryId: 'cat1' },
{ id: '003',
name: 'item3',
description: 'description of item3',
categoryId: 'cat1' }
]
},
{ id: 'cat2',
name: 'Category2',
items:
[ { id: '002',
name: 'item2',
description: 'description of item2',
categoryId: 'cat2'
}
]
},
{ id: '',
name: '',
items:
[ { id: '004',
name: 'item4',
description: 'description of item4' } ] }
]
*/
Assuming the variables categories
and items
are assigned as you defined above: 假设变量
categories
和items
的分配如上定义:
const keyedCategories = _(categories)
.concat({ id: '', name: '' })
.keyBy('id')
.value();
const groupedItems = _.groupBy(items, (item) => _.get(item, 'categoryId', ''));
const result = _.reduce(groupedItems, (acc, value, key) => {
const { id: categoryId, name } = keyedCategories[key];
return _.concat(acc, { categoryId, name, items: value });
}, []);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.