如何根据javascript中的键合并和替换两个数组中的对象?

Posted

技术标签:

【中文标题】如何根据javascript中的键合并和替换两个数组中的对象?【英文标题】:How to merge and replace objects from two arrays based on a key in javascript? 【发布时间】:2019-06-16 17:01:01 【问题描述】:

我有两个数组对象(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 应该是什么? 这里的use case 是什么。 list 1list 2 的典型大小是多少?他们总是平等的吗?在出现问题之前,我不会太担心性能。当代码库很大时,瓶颈通常在其他地方。这些天机器可以非常有效地处理loops等。 @JackBashford - 我得到了预期的输出。只是想以高效和性能的方式减少代码。 @SamuelToh,'list-1' 和 'list-2' 的大小将会改变.. 大多数情况下,list1 和 list2 的格式会有所不同。只是我添加了 smaple json 以供理解... @RSKMR 元素的顺序是否固定,即 arrayList1 的第一个元素,然后是 arrayList2? 【参考方案1】:

您也可以使用.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; 

【讨论】:

由于 Object.values does not guarantee to come in any particular order 我建议使用 Map 代替:[ ...[] .concat(arrayList1, arrayList2) .reduce((r, c) => r.set(c.type, Object.assign(r.get(c.type) || , c)), r, new Map()) .values(), ];【参考方案2】:

您可以使用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。【参考方案3】:

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

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));

【讨论】:

未达到预期输出。请检查我有问题的输出。【参考方案4】:

如果您在 arrayList2 之前并不完全需要 arrayList1,您可以使用这种简单的方法。 我所做的是我已经解构了 arrayList2 的所有元素,并且只有 arrayList1 的键不存在于 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)

【讨论】:

以上是关于如何根据javascript中的键合并和替换两个数组中的对象?的主要内容,如果未能解决你的问题,请参考以下文章

Python列表元素为字典时,如何根据其中某个相同的键值进行元素合并

如何根据对象数组中的键获取值javascript

Scala - 基于 Spark 中的键合并两个 RDD

更改字典键时出错

R中的条件合并/替换

在 PowerShell 中合并哈希表:如何?