JavaScript - «Объединение» двух одинаковых массивов объектов - PullRequest
0 голосов
/ 13 января 2019

Допустим, у меня есть следующие два массива:

let arr1 = [ { id: "1234567890", name: "Someone", other: "unneeded", props: 123 } ... ];
let arr2 = [ { id: "1234567890", points: 100, other: "unneeded", props: 456 } ... ];

Мне нужно объединить их, основываясь на имени и точках по идентификатору, который выглядит следующим образом:

[ { 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(), но это не похоже на ответ (если я не ошибаюсь). Как я могу это сделать?

Ответы [ 2 ]

0 голосов
/ 13 января 2019

Одним из решений, которое вы можете попробовать, является Webworkers . Если вы не использовали их раньше, они могут запускать сценарии в отдельном потоке, что позволяет вам использовать несколько ядер для обработки чего-либо. Они отлично подходят для распараллеливаемых задач, то есть задач, которые можно разбить без сбоев. Они вполне подойдут для вашего случая использования, поскольку вы просто делаете большую карту для ваших данных.

Прежде чем идти по этому пути, вы должны быть предупреждены о том, что у веб-работников есть некоторые накладные расходы. Чтобы получить данные для веб-работника, вы должны сериализовать их в поток, а затем десериализовать, когда они вернутся. Однако, если вы разделите свои задачи на отдельные работы и будете выполнять их параллельно, вы сможете смягчить некоторые из них.

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

Вы можете спросить о сериализации, и это происходит автоматически. Веб-работники имеют собственную глобальную область видимости, и в результате сериализации вы можете отправлять объекты, массивы и примитивы. Все это можно сериализовать. Однако объекты с пользовательскими свойствами и классами будут выдавать ошибки. За кулисами это в основном берет ваши данные и делает JSON.stringify({{your data}}), а затем в данных веб-работника становится результатом JSON.parse({{serialized data}}).

Поскольку эта работа выполняется в отдельных потоках, вы не увидите каких-либо блокировок в главном потоке, где работает ваше приложение. Если вы попытаетесь обработать слишком много сразу, сериализация будет заметна, поскольку она блокируется до завершения.

0 голосов
/ 13 января 2019

Вы можете создать 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...