如何通过键合并两个对象数组并将唯一键保留在单个对象数组中?

时间:2020-10-31 16:54:56

标签: javascript

我想合并两个对象数组,其中具有相同ID的对象将合并属性,而具有唯一ID的对象将成为 merged 数组中自己的对象。以下代码在第一部分中将合并相似的ID,但是如何将具有 arr2 中唯一ID的对象保留在合并数组中,并使其与可变长度的数组一起使用?

预期输出:

[
  {
    "id": "1",
    "date": "2017-01-24",
    "name": "test"
  },
  {
    "id": "2",
    "date": "2017-01-22",
    "bar": "foo"
  }
  { "id": "3",
    "foo": "bar",
  }
]

代码:

let arr1 = [{
    id: '1',
    createdDate: '2017-01-24'
  },
  {
    id: '2',
    createdDate: '2017-01-22'
  },
];

let arr2 = [{
    id: '1',
    name: 'test'
  },
  {
    id: '3',
    foo: 'bar'
  },
  {
    id: '2',
    bar: 'foo'
  },
];

let merged = [];

for (let i = 0; i < arr1.length; i++) {
  merged.push({
      ...arr1[i],
      ...arr2.find((itmInner) => itmInner.id === arr1[i].id),
    },

  );
}

console.log(merged);

5 个答案:

答案 0 :(得分:1)

依次遍历较大的数组,该数组包含较小的数组,

let arr1=[{id:"1",createdDate:"2017-01-24"},{id:"2",createdDate:"2017-01-22"}],arr2=[{id:"1",name:"test"},{id:"3",foo:"bar"},{id:"2",bar:"foo"}];

const merged = arr2.map(item => ({
  ...arr1.find(({ id }) => id === item.id),
  ...item
}));
console.log(merged);

(如果顺序很重要,那么以后也可以排序)

如果您事先不知道哪个/如果一个包含另一个,则使用一个对象首先按ID索引合并的对象:

let arr1=[{id:"1",createdDate:"2017-01-24"},{id:"2",createdDate:"2017-01-22"}],arr2=[{id:"1",name:"test"},{id:"3",foo:"bar"},{id:"2",bar:"foo"}];

const resultObj = Object.fromEntries(
  arr1.map(
    item => [item.id, { ...item }]
  )
);
for (const item of arr2) {
  if (!resultObj[item.id]) {
    resultObj[item.id] = item;
  } else {
    Object.assign(resultObj[item.id], item);
  }
}
const merged = Object.values(resultObj);
console.log(merged);

答案 1 :(得分:0)

您可以按以下方法创建包含arr1arr2组元素的新对象,方法是按id键,合并的数组将存储在对象值上。

您可以使用Object.values函数获取对象值。

let arr1 = [{
    id: '1',
    createdDate: '2017-01-24'
  },
  {
    id: '2',
    createdDate: '2017-01-22'
  },
];

let arr2 = [{
    id: '1',
    name: 'test'
  },
  {
    id: '3',
    foo: 'bar'
  },
  {
    id: '2',
    bar: 'foo'
  },
];

const groupById = {};
for (let i = 0; i < Math.min(arr1.length, arr2.length); i ++) {
  if (arr1[i]) {
    groupById[arr1[i].id] = { ...groupById[arr1[i].id], ...arr1[i] };
  }
  if (arr2[i]) {
    groupById[arr2[i].id] = { ...groupById[arr2[i].id], ...arr2[i] };
  }
}

const merged = Object.values(groupById);
console.log(merged);

答案 2 :(得分:0)

通过将对象存储在哈希表中(按id排序),可以采用单循环方法。

const
    mergeTo = (target, objects = {}) => o => {
        if (!objects[o.id]) target.push(objects[o.id] = {});
        Object.assign(objects[o.id], o);
    },
    array1 = [{ id: '1', createdDate: '2017-01-24' }, { id: '2', createdDate: '2017-01-22' }],
    array2 = [{ id: '1', name: 'test' }, { id: '3', foo: 'bar' }, { id: '2', bar: 'foo' }],
    merged = [],
    merge = mergeTo(merged);
    
array1.forEach(merge);
array2.forEach(merge);

console.log(merged);
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 3 :(得分:0)

另一种方法可以按原样合并两个数组,然后“压缩”它:

let arr1 = [{
    id: '1',
    createdDate: '2017-01-24'
  },
  {
    id: '2',
    createdDate: '2017-01-22'
  },
];

let arr2 = [{
    id: '1',
    name: 'test'
  },
  {
    id: '3',
    foo: 'bar'
  },
  {
    id: '2',
    bar: 'foo'
  },
];

let merged = [...arr1, ...arr2].reduce(
 (acc, {id, ...props}) => 
    (acc.set(id, {...(acc.get(id) || {}), ...props}), acc), new Map());

console.log([...merged].map( ([id, props]) => ({id, ...props}) ))

请注意,您可能不需要最后一行,它仅用于获取所需的格式,因为上述reduce使用Map作为累加器,您已经可以使用例如merged.get("1").createdDate(其中"1"是ID)。

由于您在一开始就通过合并它们来处理一个数组,因此您不必在意它们的长度,甚至也不关心其中包含更多元素的数组。您也可以有多个数组而不是只有两个,这没关系。

重要的是顺序:如果一个以上的数组包含相同的“ id”属性,则您获得的值就是最近添加的数组中的值(在上面的示例中,将为{ {1}}。

答案 4 :(得分:0)

您可以编写函数以将数组简化为一个对象,然后从该对象中提取值,这将返回所需的值。您可以看到以下代码:

let arr1 = [
  {
    id: '1',
    createdDate: '2017-01-24',
  },
  {
    id: '2',
    createdDate: '2017-01-22',
  },
];

let arr2 = [
  {
    id: '1',
    name: 'test',
  },
  {
    id: '3',
    foo: 'bar',
  },
  {
    id: '2',
    bar: 'foo',
  },
];

function merge(arr1 = [], arr2 = []) {
  return Object.values(
    arr1.concat(arr2).reduce(
      (acc, curr) => ({
        ...acc,
        [curr.id]: { ...(acc[curr.id] ?? {}), ...curr },
      }),
      {}
    )
  );
}

const merged = merge(arr1, arr2);

输出:

[
  {
    "id": "1",
    "createdDate": "2017-01-24",
    "name": "test"
  },
  {
    "id": "2",
    "createdDate": "2017-01-22",
    "bar": "foo"
  },
  {
    "id": "3",
    "foo": "bar"
  }
]
相关问题