通过ID合并两个对象数组

时间:2018-11-24 21:30:19

标签: javascript arrays json reactjs

我有两个这样的数组:

let a = [{id: 1, price: 50}, {id: 2, price: 30}, {id: 1, price: 40}, {id: null, price: 80}];
let b = [{id: 1, name: "apple"}, {id: 2, name: "orange"}];

现在我想要这样的结果:

result = [ {name: "apple", prices: [{id: 1, price: 50}, {id: 1, price: 40}]}, {name: "orange", prices: [{id: 2, price: 30}]}, {name: "others", prices: [{id: null, price: 80}]}] 

我想根据其a将数组b的元素映射到第二个数组id的名称。

4 个答案:

答案 0 :(得分:1)

这是一种使用reduce构建查找集并避免在b中重复搜索的方法。另一个简化过程是使用查找表按名称构建结果数组。最后,map用于格式化结果。

时间复杂度是线性的(三遍具有大量恒定时间的对象查找)。

let a = [{id: 1, price: 50}, {id: 2, price: 30}, {id: 1, price: 40}, {id: null, price: 80}];
let b = [{id: 1, name: "apple"}, {id: 2, name: "orange"}];

const lookup = b.reduce((a, e) => {
  a[e.id] = e.name;
  return a;
}, {});

const result = Object.entries(
  a.reduce((a, e) => {
    const key = lookup[e.id] || "others";
    
    if (!(key in a)) {
      a[key] = [];
    }

    a[key].push(e);
    return a;
  }, {})
).map(e => ({name: e[0], prices: e[1]}));

console.log(result);

答案 1 :(得分:1)

最好不要在结果的价格部分重复id,因为ID属于名称。

我建议使用临时map(出于效率考虑):

let a = [{id: 1, price: 50}, {id: 2, price: 30}, {id: 1, price: 40}, {id: null, price: 80}];
let b = [{id: 1, name: "apple"}, {id: 2, name: "orange"}];

const map = new Map(b.map(o => [o.id, Object.assign(o, { prices: [] })]))
            .set(null, {id: null, name: "others", prices: []});

a.forEach(o => map.get(o.id).prices.push(o.price));

const result = [...map.values()];

console.log(result);

答案 2 :(得分:1)

是的,您只需使用地图和过滤器即可

let a = [{id: 1, price: 50}, {id: 2, price: 30}, {id: 1, price: 40}, {id: null, price: 80}];
let b = [{id: 1, name: "apple"}, {id: 2, name: "orange"}];

b.map(({ name, id }) => ({
  name,
  id,
  prices: a.filter(item => item.id === id).map(({ price }) => price)
}));

答案 3 :(得分:1)

如果将两个数组组合在一起,则可以使用单个Array.reduceObject.values来完成此操作:

let a = [{id: 1, price: 50}, {id: 2, price: 30}, {id: 1, price: 40}, {id: null, price: 80}];
let b = [{id: 1, name: "apple"}, {id: 2, name: "orange"}];

const result = Object.values([...b, ...a].reduce((r, c) => {
  if ('name' in c || c.id == null)
    r[c.id || 'others'] = ({name: c.name || 'others', prices: []})

  if ('name' in c)
    return r
  else if (c.id != null)
    r[c.id].prices.push(c)
  else
    r['others'].prices.push(c)
  return r
}, {}))

console.log(result)

想法是从包含名称的名称开始,以便分组首先创建对象分组,然后仅填充组数组。