Отличный способ сравнить два массива объектов с v8 и filter / find - PullRequest
3 голосов
/ 21 сентября 2019

У меня есть 2 (ну,> 2) массива объектов со структурой, подобной этой:

const mainArr = [
  { article: "somename-1", price: 10, found: [] },
  { article: "somename-2", price: 20, found: [] },...
];
const toCompareArr = [
  { article: "somename-1", articleFormatted: "0somename-1", price: 20 },
  { article: "somename-3", articleFormatted: "0somename-3", price: 20 },...
];

И для mainArr я пытаюсь найти все вхождения во 2-м toCompareArr массив (в основном - мне нужно создать компаратор цен для разных поставщиков), например:

let i = 0;
let j = 0;
const iMax = mainArr.length;
const jMax = toCompareArr.length;
for (; i < iMax; i++) {
  for (; j < jMax; j++) {
    if (
      mainArr[i].article === toCompareArr[j].article ||
      mainArr[i].article === `00-${toCompareArr[j].articleFormatted}`
    ) {
      mainArr[i].found.push(toCompareArr[j]);
    }
  }

  j = 0;
}

// also tried like this (for + for seems to be more speedy):
/*
let found;
for (; i < iMax; i++) {
  found = toCompareArr.filter(
    item =>
      item.article === mainArr[i].article ||
      item.articleFormatted === mainArr[i].article
  );

  if (found) {
    mainArr[i].found.push(found);
  }
}
*/

как результат Я хочу получить:

[
  {
    article: "somename-1",
    price: 10,
    found: [
      { article: "somename-1", articleFormatted: "0somename-1", price: 20 }
    ]
  },
  { article: "somename-2", price: 20, found: [] }
];

но это очень медленно, когда у меня много данных (обычно в каждом элементе массива около 80k-100k)

И я застрял ... Может быть, естьспособ улучшить производительность фильтра и найти здесь?Я использую последние функции Node & V8.Теперь для сравнения потребовалось около 5 минут, если это будет 50% (скажем, 2 минуты - это намного лучше)

Может быть, каким-то образом мне следует полностью заново изобрести свою логику?использовать некоторые алгоритмы (хотелось бы знать - какой именно)

Ответы [ 2 ]

4 голосов
/ 21 сентября 2019

Можно взять Map.

const
    mainArr = [{ article: "somename-1", price: 10, found: [] }, { article: "somename-2", price: 20, found: [] }],
    toCompareArr = [{ article: "somename-1", articleFormatted: "0somename-1", price: 20 }, { article: "somename-3", articleFormatted: "0somename-3", price: 20 }],
    map = mainArr.reduce((m, o) => m.set(o.article, o), new Map);

for (let item of toCompareArr) {
    let object = map.get(item.article) || map.get('00-' + item.articleFormatted);
    if (!object) continue;
    object.found.push(item);
}

console.log(mainArr);
.as-console-wrapper { max-height: 100% !important; top: 0; }
4 голосов
/ 21 сентября 2019

Это очень медленно, когда у меня много данных - обычно в каждом

было бы около 80k-100k элементов массива * Используйте для этой задачи базу данных ,Хорошая СУБД должна уметь выполнять это сравнение менее чем за секунду, используя hash join или подобную технику.Конечно, вы можете повторно реализовать это в node.js, если вы настаиваете - используйте идентификатор статьи в качестве ключа в Map.

...