合并与第二组对象的Javascript数组和组

问题描述:

我有两个对象数组。一个数组包含项目列表,另一个数组包含类别列表。我想创建一个基于categoryIds的新数组。我尝试使用lodash。但是,无法得到正确的解决方案。合并与第二组对象的Javascript数组和组

我可以使用循环来做到这一点。但是,我正在寻找更干净的方法。

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

预计输出

[ 
{ 
    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/

感谢您的帮助

+0

* - 哪里是你的企图:“我可以用循环做到这一点。”?你的小提琴只包括输入对象和所需的输出。 – nnnnnn

+0

对不起。我已经更新了jsfiddle。请看一看。 https://jsfiddle.net/sfpd3ppn/1/ – jintoppy

可以完成使用reduce期望的结果。我们将从原始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' } ] } 
] 
*/ 

下面的伎俩:

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

我用.concat()创建一个新的类别数组保存原始categories项目加上一个“空”类别开始。然后,我.map()该数组返回类别对象与您所需的输出结构,其中每个具有items阵列由.filter()数组生成的原始items数组。

(注意:outputitems阵列包含对在原始items输入相同的对象,不是他们的副本引用。如果你想拷贝你可以在.filter()后再添.map()。)

假设变量categoriesitems如你在上面定义的分配:

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 }); 
}, []);