合并两个对象数组

3

假设我有这两个数组:

const initial: Array<GivenObj> = [
  {name: 'a', times: 40, other: 50},
  {name: 'b', times: 10, other: 15},
  {name: 'c', times: 15, other: 12}
];

const toBeMerged: Array<GivenObj> = [
  {name: 'a', times: 45, other: 30},
  {name: 'c', times: 10, other: 10},
  {name: 'd', times: 23, other: 10}
];

这两个数组包含不同的值,但具有相似的键。我需要将这些数据聚合到一个数组中,该数组将包含它们的所有值,但每个键只出现一次。

在代码中,应按以下方式聚合上述两个数组:

const aggregated: Array<GivenObj> = [
  {name: 'a', times: 85, other: 80},
  {name: 'b', times: 10, other: 15},
  {name: 'c', times: 25, other: 22},
  {name: 'd', times: 23, other: 10}
];

我在想,如何最好地将两个数组的数据聚合起来。

1
你需要循环遍历,找到重复的内容,再进行计算。实际上,没有一个现成的方法可以将属性值合并。你试过了吗? - isherwood
1
请发布您的代码。 - b_dubb
atimes结果应该是85,而c对于两个值都是错误的。 - Andy
1
谁在对几乎所有答案进行负评? - 0.sh
2
@Andy 谢谢,数值已经固定。 - Eliya Cohen
显示剩余3条评论
7个回答

3
我会将这两个数组合并,然后对组合数组运行reduce方法来处理。在reduce方法内部,它首先检查是否存在具有该名称的条目,如果不存在,则将该条目推入结果数组中。如果找到现有条目,则创建任何不存在的属性,并添加已经存在的任何数值属性的值。这应该足够灵活以适应您实际的用例。

const initial = [
  {name: 'a', times: 40, other: 50},
  {name: 'b', times: 10, other: 15},
  {name: 'c', times: 15, other: 12}
];

const toBeMerged = [
  {name: 'a', times: 45, other: 30},
  {name: 'c', times: 10, other: 10},
  {name: 'd', times: 23, other: 10}
];

const result = [ ...initial, ...toBeMerged ].reduce((arr, t) => {
  let existing = arr.filter(x => x.name == t.name)[0]
  if(!existing) arr.push(t)
  else {
    const keys = Object.keys(t)
    keys.forEach(key => {
      if(!existing.hasOwnProperty(key)) existing[key] = t[key]
      else if(typeof existing[key] === "number") existing[key] += t[key]
    })
  }
  
  return arr
}, [])

console.log(result)


1
你可以减少给定的数据并查找相同的name,然后更新,否则添加一个新对象。
它需要:
- 一个包含来自initialtoBeMerged项目的新数组, - 通过以下方式减少项目: - 在累加器r中查找具有相同name的项目, - 检查是否未找到该项目,然后返回收集到的项目和实际对象的副本的新数组 - 否则增加所需属性的一些值。

const
    initial = [{ name: 'a', times: 40, other: 50 }, { name: 'b', times: 10, other: 15 }, { name: 'c', times: 15, other: 12 }],
    toBeMerged = [{ name: 'a', times: 45, other: 30 }, { name: 'c', times: 10, other: 10 }, { name: 'd', times: 23, other: 10 }],
    merged = [...initial, ...toBeMerged].reduce((r, o) => {
        var temp = r.find(p => o.name === p.name);
        if (!temp) return [...r, { ...o }];
        temp.times += o.times;
        temp.other += o.other;
        return r;
    }, []);

console.log(merged);


@Shidersz 没有头绪。几乎所有的答案都因无缘无故而被踩了。 - Eliya Cohen

0

以下是我过去解决这个问题的方法:

  1. 创建一个 final 数组,它将包含最终结果。
  2. 使用数组的 concat 方法合并数组。
  3. 按照 name 属性对连接后的数组进行排序,这意味着所有 a 的元素将按顺序排列,然后是 b 的元素等等。
  4. 使用 forEach 方法迭代连接、排序后的数组。如果当前元素与 final 数组的最后一个元素具有相同的 name 属性,则将 el 的数字属性添加到 final 数组的最后一个元素中。否则,将 el 添加到最终数组的末尾。

const initial = [
  {name: 'a', times: 40, other: 50},
  {name: 'b', times: 10, other: 15},
  {name: 'c', times: 15, other: 12}
];

const toBeMerged = [
  {name: 'a', times: 45, other: 30},
  {name: 'c', times: 10, other: 10},
  {name: 'd', times: 23, other: 10}
];

let final = [];

initial.concat(toBeMerged).sort((a, b) => a.name > b.name).forEach(el => {
  if (final.length > 0 && el.name === final[final.length - 1].name) {
    final[final.length - 1].times += el.times;
    final[final.length - 1].other += el.other;
  } else {
    final.push(el);
  }
})

console.log(final);


0

你可以通过 reduce 来完成它。

  1. 首先使用 concat 合并两个数组。
  2. 现在在合并后的数组上,使用 reduce 检查对象属性是否已经存在于 output 中,如果是,则将 timesother 添加到现有属性中,否则添加一个新属性。

const initial= [{name: 'a', times: 40, other: 50},{name: 'b', times: 10, other: 15},{name: 'c', times: 15, other: 12}];
const toBeMerged= [{name: 'a', times: 45, other: 30},{name: 'c', times: 10, other: 10},{name: 'd', times: 23, other: 10}];
let temp = initial.concat(toBeMerged)

let op = temp.reduce((output,current)=>{
  if( output[current.name] ){
    output[current.name].times += current.times
    output[current.name].other += current.other
  } else{
    output[current.name] = current;
  }
  return output;
},{})

console.log(Object.values(op))


0

试试这段代码

const initial = [
  {name: 'a', times: 40, other: 50},
  {name: 'b', times: 10, other: 15},
  {name: 'c', times: 15, other: 12}
];

const toBeMerged = [
  {name: 'a', times: 45, other: 30},
  {name: 'c', times: 10, other: 10},
  {name: 'd', times: 23, other: 10}
];

//console.log(initial);

function arrayUnique(array) {
    var a = array.concat();
    for(var i=0; i<a.length; ++i) {
        for(var j=i+1; j<a.length; ++j) {
            if(a[i].name === a[j].name)
            {
                a[i].times +=a[j].times;
                a[i].other +=a[j].other;
                a.splice(j--, 1);
            }
        }
    }

    return a;
}


    // Merges both arrays and gets unique items
var array = arrayUnique(initial.concat(toBeMerged));
console.log(array);


0

这里有一种方法,使用reduce()findIndex()在要合并的新数组上进行操作。如果要合并的新对象已经存在(即name属性与某个对象匹配),则我们增加其余匹配属性并添加不存在的属性,否则我们将整个新对象推入:

const initial = [
  {name: 'a', times: 40, other: 50},
  {name: 'b', times: 10, other: 15},
  {name: 'c', times: 15, other: 12}
];

const toBeMerged = [
  {name: 'a', times: 45, other: 30, another: 76},
  {name: 'c', times: 10, other: 10},
  {name: 'd', times: 23, other: 10}
];

let newArray = toBeMerged.reduce((res, curr) =>
{
    let found = res.findIndex(x => x.name === curr.name);

    if (found >= 0)
    {
        res[found] = Object.keys(curr).reduce((r, c) =>
        {
           r[[c]] = (r[[c]] && c !== 'name') ? r[[c]] + curr[[c]] : curr[[c]];
           return r;
        }, res[found]);
    }
    else
    {
        res.push(curr);
    }

    return res;

}, initial);

console.log(newArray);


0

使用展开运算符、解构、Array#reduce、Object#values和Map

const initial=[{name:'a',times:40,other:50},{name:'b',times:10,other:15},{name:'c',times:15,other:12}];const toBeMerged=[{name:'a',times:45,other:30},{name:'c',times:10,other:10},{name:'d',times:23,other:10}]

const res = [...[...initial, ...toBeMerged]
.reduce((a,{name,times,other})=>{
    const b = a.get(name);
    return a.set(name,{name, times: (b?b.times:0) + times, other: (b?b.other:0) + other});
}, new Map()).values()];

console.log(res);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接