假设我有以下两个数组:
let arr1 = [ { id: "1234567890", name: "Someone", other: "unneeded", props: 123 } ... ];
let arr2 = [ { id: "1234567890", points: 100, other: "unneeded", props: 456 } ... ];
我需要根据名称和要点的ID结合起来,如下所示:
[ { id: "1234567890", name: "Someone", points: 100 } ... ]
一种选择是像这样映射它们:
let final = arr1.map(u => ({
id: u.id,
name: u.name,
points: arr2.find(uu => uu.id === u.id)
}));
但是,这对于较大的数组(成千上万的条目)而言效率不高,因为find()
每次都会遍历该数组。我正在努力提高效率。我读了Array.reduce()
,但这似乎不是答案(除非我错了)。我该怎么办?
答案 0 :(得分:2)
您可以从第二个数组的对象中创建一个Map
,以便您可以在恒定时间内通过id直接访问相应的对象:
let arr1 = [
{id: 1234567890, name: "Someone", other: "unneeded", props: 123},
{id: 1234567891, name: "Someone1", other: "unneeded1", props: 124},
{id: 1234567892, name: "Someone2", other: "unneeded2", props: 125}
];
let arr2 = [
{id: 1234567890, points: 100, other: "unneeded", props: 456},
{id: 1234567891, points: 101, other: "unneeded", props: 457},
{id: 1234567892, points: 102, other: "unneeded", props: 458}
];
let arr2Map = arr2.reduce((a, c) => {
a.set(c.id, c);
return a;
}, new Map());
let final = arr1.map(({id, name, points}) =>
({id, name, points: arr2Map.get(id).points || points}));
console.log(final);
答案 1 :(得分:0)
您可以尝试的一种解决方案是Webworkers。如果您以前从未使用过它们,则它们可以在单独的线程中运行脚本,从本质上讲,您可以使用多个内核来处理某些事情。它们非常适合可并行化的任务,这意味着可以分解而没有任何中断的任务。它们将非常适合您的用例,因为您只是对数据做一个大的映射。
在走这条路之前,尽管应该警告您Web工作者有一些开销。为了使数据进入Webworker,您必须将其序列化到线程中,然后在返回时反序列化。但是,如果您将任务分解为单独的工作并使其并行运行,那么您应该可以减轻其中的一些负担。
// app.js
let largeArray = []; // contains the large amount of arrays to map
let outputArray = [];
while(largeArray.length){
let worker = new Worker('/path/to/worker/script.js');
worker.postMessage({
chunk: largeArray.splice(0,1000)
});
worker.onmessage = evt => {
let data = evt.data;
outputArray = outputArray.concat(data);
worker.terminate();
}
}
另外有一个工作脚本,也许与此可供参考的脚本相似。
// workerScript.js
self.onmessage = ({data: {chunk}}) => {
let final = chunk.map(u => ({
id: u.id,
name: u.name,
points: arr2.find(uu => uu.id === u.id)
}));
self.postMessage(final);
}
您可能会询问序列化,这是自动发生的。 Webworkers有自己的全局范围,作为序列化的结果,您可以发送对象,数组和基元。所有这些都可以序列化。但是具有自定义属性和类的对象将引发错误。在幕后,基本上是在获取您的数据并进行JSON.stringify({{your data}})
,然后在Webworker中,数据成为JSON.parse({{serialized data}})
的结果。
由于这项工作是在单独的线程中进行的,因此您在运行应用程序的主线程上不会看到任何阻塞。不过,如果您尝试一次处理太多内容,那么序列化会很明显,因为它会阻塞直到完成。