JavaScript通过ID合并对象

81

在Javascript中合并两个数组的正确方式是什么?

我有两个数组(例如):

var a1 = [{ id : 1, name : "test"}, { id : 2, name : "test2"}]
var a2 = [{ id : 1, count : "1"}, {id : 2, count : "2"}]

我希望最终能够得到类似以下的结果:

var a3 = [{ id : 1, name : "test", count : "1"}, 
          { id : 2, name : "test2", count : "2"}]

根据'id'字段合并这两个数组,并且只是简单地添加额外的数据。

我尝试使用_.union来实现这个功能,但它只是将第二个数组中的值覆盖了第一个数组。


1
所以你实际想要做的是合并这些对象。 - JJJ
你的语法无效。你有一个合法的例子吗? - Mark Reed
请参见http://stackoverflow.com/questions/10688569/javascript-extend-array。 - megawac
与 https://dev59.com/OFoU5IYBdhLWcg3w1pX2 密切相关。 - Julian
@dippas OP想要根据ID合并对象,而不仅仅是合并数组。而且那些答案中的去重在对象上也不起作用。 - gre_gor
18个回答

2

一个可用的TypeScript版本:

export default class Merge {
  static byKey(a1: any[], a2: any[], key: string) {
    const res = a1.concat(a2).reduce((acc, x) => {
      acc[x[key]] = Object.assign(acc[x[key]] || {}, x);
      return acc;
    }, {});

    return Object.entries(res).map(pair => {
      const [, value] = pair;
      return value;
    });
  }
}

test("Merge", async () => {
  const a1 = [{ id: "1", value: "1" }, { id: "2", value: "2" }];
  const a2 = [{ id: "2", value: "3" }];

  expect(Merge.byKey(a1, a2, "id")).toStrictEqual([
    {
      id: "1",
      value: "1"
    },
    { id: "2", value: "3" }
  ]);
});


1
尝试这个。
var a1 = [{ id : 1, name : "test"}, { id : 2, name : "test2"}]
var a2 = [{ id : 1, count : "1"}, {id : 2, count : "2"}]
let arr3 = a1.map((item, i) => Object.assign({}, item, a2[i]));

console.log(arr3);

1
这个怎么样?
const mergeArrayObjects = (arr1: any[], arr2: any[], mergeByKey: string): any[] => {
  const updatedArr = [];
  for (const obj of arr1) {
    const arr1ValueInArr2 = arr2.find(
      a => a[mergeByKey] === obj[mergeByKey],
    );
    if (arr1ValueInArr2) {
      updatedArr.push(Object.assign(obj, arr1ValueInArr2));
    } else {
      updatedArr.push(obj);
    }
  }
  const mergeByKeyValuesInArr1 = arr1.map(a => a[mergeByKey]);
  const remainingObjInArr2 = arr2.filter(a => !mergeByKeyValuesInArr1.includes(a[mergeByKey]) )
  return updatedArr.concat(remainingObjInArr2)
}

0
const a3 = a1.map(it1 => {
   it1.test = a2.find(it2 => it2.id === it1.id).test
   return it1
 })

8
测试是什么东西? - SuperUberDuper

0
你可以编写一个简单的对象合并函数,像这样:
function mergeObject(cake, icing) {
    var icedCake = {}, ingredient;
    for (ingredient in cake)
        icedCake[ingredient] = cake[ingredient];
    for (ingredient in icing)
        icedCake[ingredient] = icing[ingredient];
    return icedCake;
}

接下来,您需要使用双重循环将其应用于您的数据结构。
var i, j, a3 = a1.slice();
for (i = 0; i < a2.length; ++i)                // for each item in a2
    for (j = 0; i < a3.length; ++i)            // look at items in other array
        if (a2[i]['id'] === a3[j]['id'])       // if matching id
            a3[j] = mergeObject(a3[j], a2[i]); // merge

你也可以将mergeObject用作简单的克隆,只需将一个参数传递为空对象即可。


-1
如果您在两个具有相同ID的数组中恰好拥有相同数量的项目,则可以执行以下操作。
const mergedArr = arr1.map((item, i) => {
  if (item.ID === arr2[i].ID) {
    return Object.assign({}, item, arr2[i]);
  }
});

-2
a1.map(x => a2.find(y => y.id === x.id))

这并不合并任何东西。 - gre_gor
回答需要支持信息 您的回答可以通过提供更多的支持信息来改进。请[编辑]以添加进一步的细节,例如引用或文档,以便他人可以确认您的回答是否正确。您可以在帮助中心找到关于如何撰写良好回答的更多信息。 - moken

-3

这些都对我没用。我自己写了一个:

const formatteddata=data.reduce((a1,a2)=>{

for (let t=0; t<a1.length; t++)
    {var id1=a1[t].id
            for (let tt=0; tt<a2.length; tt++)
                {var id2=a2[tt].id
                    if(id1==date2)
                      {a1[t]={...a1[t],...a2[tt]}}
                }
    }
return a1

})

可以适用于任意数量的对象数组,数组长度不一,并且日期不总是重合的。


再说一遍,这并没有回答问题。 - Christian Matthew
这根本不起作用。data是什么?为什么有date2?这种不当使用reduce的意义何在?这段代码就是胡扯。 - gre_gor

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