通过键/值合并数组对象

问题描述:

我有两个单独的对象数组,我需要合并,如果特定的键值匹配。分析数据后可能会更有意义:通过键/值合并数组对象

阵列1

let categories = [ 
    { id: 5, slug: 'category-5', items: [] }, 
    { id: 4, slug: 'category-4', items: [] }, 
    { id: 3, slug: 'category-3', items: [] }, 
] 

阵列2

let items = [ 
    { id: 5, data: [{ title: 'item title', description: 'item description' }] }, 
    { id: 5, data: [{ title: 'item title 2', description: 'item description 2' }] }, 
    { id: 4, data: [{ title: 'item title 4', description: 'item description 4' }] }, 
] 

期望输出

let mergedOutput = [ 
    { id: 5, slug: 'category-5', 
     items: [ 
      { title: 'item title', description: 'item description' }, 
      { title: 'item title 2', description: 'item description 2' } 
     ] 
    }, 
    { id: 4, slug: 'category-4', 
     items: [ 
      { title: 'item title 4', description: 'item description 4' }, 
     ] 
    }, 
    { id: 3, slug: 'category-3', items: [] }, 
] 

因此....我需要添加阵列2阵列1如果他们的id匹配。 阵列1将保持不变,但如果阵列2场比赛中,项目阵列1(空)将阵列的数据属性来代替2

我知道这属性是一个非常基本的和多余的问题,但我找不到我的用例/对象结构的资源。

我能够轻松地将数组与lodash分组 - 所以如果有与该库类似的解决方案 - 那很好!或者只是一些方向就足够了。

在此先感谢!

您可以循环第一个数组,然后使用filter获取与当前元素具有相同id的对象,并将该项添加到当前对象。

let categories = [ 
 
    { id: 5, slug: 'category-5', items: [] }, 
 
    { id: 4, slug: 'category-4', items: [] }, 
 
    { id: 3, slug: 'category-3', items: [] }, 
 
] 
 

 
let items = [ 
 
    { id: 5, data: [{ title: 'item title', description: 'item description' }] }, 
 
    { id: 5, data: [{ title: 'item title 2', description: 'item description 2' }] }, 
 
    { id: 4, data: [{ title: 'item title 4', description: 'item description 4' }] }, 
 
] 
 

 
categories.forEach(function(e) { 
 
    var i = items.filter(a => a.id == e.id).map(a => a.data); 
 
    e.items = i; 
 
}) 
 

 
console.log(categories)

我会做的类别为哈希表和钥匙将ID和遍历只有所有项目。 然后你得到O(N)解决方案。

你可以减少项目分类:

let res = items.reduce((a, b) => { 
    let it = a.find(e => e.id === b.id); 
    if (! it) return a; 
    it.items = it.items.concat(b.data); 
    return a; 
}, categories); 

let categories = [{ 
 
    id: 5, 
 
    slug: 'category-5', 
 
    items: [] 
 
    }, 
 
    { 
 
    id: 4, 
 
    slug: 'category-4', 
 
    items: [] 
 
    }, 
 
    { 
 
    id: 3, 
 
    slug: 'category-3', 
 
    items: [] 
 
    }, 
 
]; 
 

 
let items = [{ 
 
    id: 5, 
 
    data: [{ 
 
     title: 'item title', 
 
     description: 'item description' 
 
    }] 
 
    }, 
 
    { 
 
    id: 5, 
 
    data: [{ 
 
     title: 'item title 2', 
 
     description: 'item description 2' 
 
    }] 
 
    }, 
 
    { 
 
    id: 4, 
 
    data: [{ 
 
     title: 'item title 4', 
 
     description: 'item description 4' 
 
    }] 
 
    }, 
 
]; 
 

 
let res = items.reduce((a, b) => { 
 
    let it = a.find(e => e.id === b.id); 
 
    if (! it) return a; 
 
    it.items = it.items.concat(b.data); 
 
    return a; 
 
}, categories); 
 

 
console.log(res);

它可能会更快得到一个对象第一的ID,所以我们不必使用find在相同的ID上多次:

function merge(result, toMerge, mergeInto) { 
    let i = 0, hm = {}; 
    for (let {id} of categories) { 
     hm[id] = i; 
     i++; 
    } 
    return toMerge.reduce((a,b) => { 
     let it = a[hm[b.id]]; 
     if (!it) return a; 
     it[mergeInto] = it[mergeInto].concat(b.data); 
     return a; 
    }, result); 
} 

let categories = [ 
 
    { id: 5, slug: 'category-5', items: [] }, 
 
    { id: 4, slug: 'category-4', items: [] }, 
 
    { id: 3, slug: 'category-3', items: [] }, 
 
]; 
 

 
let items = [ 
 
    { id: 5, data: [{ title: 'item title', description: 'item description' }] }, 
 
    { id: 5, data: [{ title: 'item title 2', description: 'item description 2' }] }, 
 
    { id: 4, data: [{ title: 'item title 4', description: 'item description 4' }] }, 
 
]; 
 

 
function merge(result, toMerge, mergeInto) { 
 
    let i = 0, hm = {}; 
 
    for (let {id} of categories) { 
 
     hm[id] = i; 
 
     i++; 
 
    } 
 
    return toMerge.reduce((a,b) => { 
 
     let it = result[hm[b.id]]; 
 
     if (!it) return a; 
 
     it[mergeInto] = it[mergeInto].concat(b.data); 
 
     return a; 
 
    }, result); 
 
} 
 

 

 
console.log(merge(categories, items, 'items'));