如何在JavaScript中基于键合并和替换两个数组中的对象?

5

我有两个数组对象(arrayList1,arrayList2),现在我想把这两个数组合并成一个数组对象。

以下是我使用的条件:

  • 根据键名type将两个数组合并为一个数组。
  • arrayList2的值将覆盖arrayList1的值。
  • 我得到了预期的输出,但我担心效率和性能。

请有经验的人简化我的代码。

注意:

  • 最好使用Array.reduce函数而不使用任何插件/库。
  • 我添加了示例输入以便理解。元素的顺序将更改,两个数组的大小也会更改。

Translated content:

我有两个数组对象(arrayList1,arrayList2),现在我想把这两个数组合并成一个数组对象。

以下是我使用的条件:

  • 根据键名type将两个数组合并为一个数组。
  • arrayList2的值将覆盖arrayList1的值。
  • 我得到了预期的输出,但我担心效率和性能。

请问有没有更高效和性能更好的方法来简化我的代码?

注意:

  • 最好使用Array.reduce函数而不使用任何插件/库。
  • 我添加了示例输入以便理解。元素的顺序将更改,两个数组的大小也会更改。

const arrayList1 = [
    { type: "A", any: 11, other: "ab", props: "1" },
    { type: "B", any: 22, other: "bc", props: "2" }, // same type
    { type: "C", any: 33, other: "df", props: "3" }
];
 
const arrayList2 = [
    { type: "D", any: 44, other: "aa", props: "11" },
    { type: "B", any: 22, other: "bb", props: "2----2" , x: 10}, // same type
    { type: "E", any: 44, other: "cc", props: "33" }
];

result = arrayList2.reduce(function (arr1, arr2) {
  let isMatchFound = false;
  arr1.forEach(function (list) {
    if (arr2.type == list.type) {
      list = Object.assign(list, arr2);
      isMatchFound = true;
    }
  });
  if (!isMatchFound) {
    arr1.push(arr2);
  }
  return arr1;
}, arrayList1);

console.log('result', JSON.stringify(result));


你希望输出什么?result 应该是什么? - Jack Bashford
这里的“用例”是什么?列表1列表2的典型大小是多少?它们总是相等的吗?在性能成为问题之前,我不会太担心它。当代码库非常庞大时,瓶颈通常出现在其他地方。如今,机器可以相当有效地处理循环等操作。 - Samuel Toh
@JackBashford - 我得到了预期的输出。只是想用高效和性能良好的方式来减少代码量。 - RSKMR
@SamuelToh,'list-1'和'list-2'的大小会发生变化.. 大多数情况下,list1、list2的格式将不同。只是为了方便理解,我添加了一些示例JSON... - RSKMR
@RSKMR 元素的顺序固定吗?即arrayList1的第一个元素,然后是arrayList2的元素? - Ashish
@Ashish - 不,顺序会改变。 - RSKMR
4个回答

2
你可以使用.reduce()Object.values()方法来获得所需的输出结果:

最初的回答

const arrayList1 = [
    { type: "A", any: 11, other: "ab", props: "1" },
    { type: "B", any: 22, other: "bc", props: "2" }, // same type
    { type: "C", any: 33, other: "df", props: "3" }
];
 
const arrayList2 = [
    { type: "D", any: 44, other: "aa", props: "11" },
    { type: "B", any: 22, other: "bb", props: "2----2" , x: 10}, // same type
    { type: "E", any: 44, other: "cc", props: "33" }
];

const result = Object.values(
   [].concat(arrayList1, arrayList2)
     .reduce((r, c) => (r[c.type] = Object.assign((r[c.type] || {}), c), r), {})
);
                 
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }


1
由于Object.values不保证以任何特定顺序返回(详情请参见:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in#Deleted_added_or_modified_properties),我建议改用Map:`[ ...[] .concat(arrayList1, arrayList2) .reduce((r, c) => r.set(c.type, Object.assign(r.get(c.type) || {}, c)), r, new Map()) .values(), ];` - HMR

1
你可以使用reduceObject.values来实现类似这样的操作。

const array1 = [
    { type: "A", any: 11, other: "ab", props: "1" },
    { type: "B", any: 22, other: "bc", props: "2" }, // same type
    { type: "C", any: 33, other: "df", props: "3" }
];
 
const array2 = [
    { type: "D", any: 44, other: "aa", props: "11" },
    { type: "B", any: 22, other: "bb", props: "2----2" , x: 10}, // same type
    { type: "E", any: 44, other: "cc", props: "33" }
];

const mapped = array1.reduce((a,t)=> (a[t.type] = t, a), {}),
      mapped2 = array2.reduce((a,t)=> (a[t.type] = t, a), {})

console.log(Object.values({...mapped, ...mapped2}))


请参见Mohammad Usman回答中的评论;Object.values中顺序不能保证,所以如果顺序很重要并且您希望它得到保证,则最好使用Map。 - HMR

0

如果你只是想让你的代码更小:

const arrayList1 = [
    { type: "A", any: 11, other: "ab", props: "1" },
    { type: "B", any: 22, other: "bc", props: "2" }, // same type
    { type: "C", any: 33, other: "df", props: "3" }
];
 
const arrayList2 = [
    { type: "D", any: 44, other: "aa", props: "11" },
    { type: "B", any: 22, other: "bb", props: "2----2" , x: 10}, // same type
    { type: "E", any: 44, other: "cc", props: "33" }
];

result = arrayList2.reduce(function(arr1, arr2) {
  if (arr1.find(({ type }) => type == arr2.type)) {
    arr1[arr1.indexOf(arr1.find(({ type }) => type == arr2.type))] = Object.assign(arr1.find(({ type }) => type == arr2.type), arr2);
    arr1.push(arr2);
  }
  return arr1;
}, arrayList1);

console.log('result', JSON.stringify(result));


预期输出未达到。请检查我在问题中的输出。 - RSKMR

0
如果您在arrayList2之前不需要确切的arrayList1,可以使用这个一行简单的方法。 我所做的是解构了arrayList2中的所有元素,仅保留那些在arrayList1中键不存在的元素。
附注:使用reduce的问题在于您必须减少最大的数组,否则您将错过更大数组的元素。

const arrayList1 = [
    { type: "A", any: 11, other: "ab", props: "1" },
    { type: "B", any: 22, other: "bc", props: "2" }, // same type
    { type: "C", any: 33, other: "df", props: "3" }
];
 
const arrayList2 = [
    { type: "D", any: 44, other: "aa", props: "11" },
    { type: "B", any: 22, other: "bb", props: "2----2" , x: 10}, // same type
    { type: "E", any: 44, other: "cc", props: "33" }
];
const output = [...arrayList2, ...arrayList1.filter(el1 => !arrayList2.some(el2 => el2.type === el1.type))]
//[].concat(arrayList2, arrayList1.filter(el1 => !arrayList2.some(el2 => el2.type === el1.type)))

console.log(output)


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