繁体   English   中英

基于相似性在javascript中合并两个对象数组的有效方法?

[英]Efficient way to merge two array of objects in javascript based on similarities?

所以我有两个对象数组:

var arr1 = [{id:1, name:John }{id:2, name:Adam }]

var arr2 = [{id:1, address:NY, number: 200}, {id:2, address:LA, number: 300}]

预期的结果是:

var newArr = [{id:1, name:John, address:NY, number: 200 }, { id:2, name:Adam, address:LA, number: 300}]

这只是数千个数据中的两个示例,我尝试通过两个数组进行映射并手动插入它们,但这总是会导致超时,因为我认为循环在后端服务器上非常繁重。 有没有一种有效的方法来执行这样的操作或像 lodash 这样的包中的轻量级解决方案来实现这一点?

除非您使用本机模块,否则 lodash 和其他包也会在内部循环这些值。

假设您使用id将元素组合在一起,这可能是您想要的

function mergeArrays(array1, array2) {
  const groups = {};

  for (const array of [array1, array2]) {
    for (const elem of array) {
      if (!groups[elem.id]) {
        groups[elem.id] = {};
      }

      Object.assign(groups[elem.id], elem);
    }
  }

  return Object.values(groups);
}

var arr1 = [{id:1, name:'John' }, {id:2, name:'Adam' }];
var arr2 = [{id:1, address:'NY', number: 200}, {id:2, address:'LA', number: 300}]

console.log(mergeArrays(arr1, arr2));

如果可以使用核心javascript实现,为什么要使用 Librarie

 var a1 = [{id:1, name:'John' },{id:2, name:'Adam' }, {id: 3, name: 'mohit'}] var a2 = [{id:1, address:'NY', number: 200}, {id:2, address:'LA', number: 300}, {id: 4, name:'dj', value: 'pj'}, {id: 5}] let a3 = [...a1, ...a2].reduce((acc, x) => { acc[x.id] = Object.assign(acc[x.id] || {}, x); return acc; }, {}); console.log('your need', Object.values(a3))

目前尚不清楚您希望如何组合元素,通过两个数组中的共享索引或共享id值。 无论哪种方式,您都可以轻松编写简单的实用程序函数,使这变得微不足道。

共享指数

首先,如果是共享索引的问题,我们可以这样做:

 const zipWith = (fn) => (xs, ys) => xs .map ((x, i) => fn (x, ys [i])) const combine = zipWith ((x, y) => ({...x, ...y})) const arr1 = [{id:1, name: 'John'}, {id:2, name: 'Adam'}], arr2 = [{id:1, address: 'NY', number: 200}, {id:2, address: 'LA', number: 300}] console .log (combine (arr1, arr2))
 .as-console-wrapper {max-height: 100% !important; top: 0}

我们编写了一个通用的帮助函数zipWith你也可以在许多实用程序库中找到它——它接受一个组合函数并返回一个函数,该函数接受两个列表并返回针对每个索引处的两个元素运行该函数的结果。 (如果数组长度不同,可能会出现奇怪的行为。)

然后我们在zipWith之上编写combine ,只需传递一个简单地合并两个对象的函数。 我们可以传递它Object .assign ,但这会修改​​它收到的第一个元素,这不是我喜欢的风格。

按 ID 分组

如果我们想使用共享ids ,我们会做一些不同的事情。 我们n O (m * n) m一个以id为键的对象和数组的值,其中包含具有该id的数组中的所有元素。 这是大多数实用程序库调用groupBy ,并将其更改为O (m + n) 我们可以在此基础上编写一个mergeBy函数,它首先使用提供的函数执行groupBy ,然后将groupBy结果的每个值中的所有元素合并为单个元素。 它看起来像这样:

 const groupBy = (fn) => (xs) => xs .reduce ((a, x, _, __, k = fn (x)) => ((a [k] = a [k] || []), (a[k] .push (x)), a), {}) const mergeBy = (fn) => (...xss) => Object .values (groupBy (fn) (xss .flat ())) .map (xs => Object .assign ({}, ...xs)) const combine = mergeBy (x => x .id) const arr1 = [{id:1, name: 'John'}, {id:2, name: 'Adam'}], arr2 = [{id:1, address: 'NY', number: 200}, {id:2, address: 'LA', number: 300}] console .log (combine (arr1, arr2))
 .as-console-wrapper {max-height: 100% !important; top: 0}

这里的mergeBy是位于groupBy之上的第二个效用函数。 combine只是传递一个 id 提取函数。 这次我们很容易使用Object .assign ,因为我们用我们的元素调用它,我们可以先给它们添加一个空对象。 1

这个版本有额外的灵活性。 它会自动处理具有相同id的多个值。 它允许您传递任意多个数组。 因此,您可以将它与具有重复id的单个数组或多个数组一起使用。

这里重要的一点是,这两个版本都很容易编写,只要你手边有一组有用的实用函数。 我可以立即使用groupByzipWith ,我可能会添加mergeBy ,这似乎也很有用。 您自己的库或久经考验的公共库是您编码工具箱中的一个很好的工具。


1. 同样,在制作此输出时没有任何对象发生变异。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM