比较三个非常大的数组并创建一个新对象

问题描述

好的,所以我在 node.js 中有三个数组,每个数组大约有 65k 个对象。它们都共享一个 ID - PARCELID、SBL 和 SBL20 是相同的。我想将来自不同数组的对象组合成一个对象,然后将其推送到最终数组中。无论出于何种原因,我得到的输出包含 130k+ 个对象。这也非常低效,所以如果有更好的方法来做到这一点,我全神贯注 - 我试图使用 map() 虽然我只能比较两个数组,而不是三个。我还有第四个我想加入。

var final = new Array();
  count=0
  TaxParcels.forEach((TaxParcel) => {
    TaxBills.forEach((TaxBill) => {
      if (TaxParcel.PARCELID == TaxBill.SBL20) {
        CodeEnforcements.forEach((CodeEnforcement) => {
          if (TaxParcel.PARCELID == CodeEnforcement.SBL) {
            parcel = {
              ID: TaxParcel.PARCELID,DETAILS: {
                TaxParcel: TaxParcel,TaxBill: TaxBill,CodeEnforcement: CodeEnforcement,},};
            final.push(parcel);
            count++
          }
        });
      }
    });
  });
  console.log(final);
  console.log(count)

解决方法

您可以通过首先创建一个 Map 来获得性能提升,该 Map 由键键控,并带有与每个键相关的空对象。然后将对象注入到这些对象中,并过滤结果以仅包含具有所有 3 个键的对象:

// sample data
let TaxParcels = [{ PARCELID: 3 },{ PARCELID: 9 },{ PARCELID: 7 }];
let TaxBills = [{ SBL20: 9 },{ SBL20: 1 },{ SBL20: 3 }];
let CodeEnforcements = [{ SBL: 3 },{ SBL: 9 },{ SBL: 1 }];

// Solution
let map = new Map([...TaxParcels,...TaxBills,...CodeEnforcements].map(o => 
    [o.PARCELID??o.SBL20??o.SBL,{}])
);

for (let o of TaxParcels) map.get(o.PARCELID).TaxParcel = o;
for (let o of TaxBills) map.get(o.SBL20).TaxBill = o;
for (let o of CodeEnforcements) map.get(o.SBL).CodeEnforcement = o;

let result = [...map.values()].filter(o => Object.keys(o).length === 3);
console.log(result);
console.log(result.length);

,

最简单(也可能不是最重要的)方法是在此处避免 forEach:即使在找到元素之后,它也会毫无意义地迭代整个数组。没有办法打破 forEach。它可以用 for-ofbreak 数组方法替换为 find 循环。这也将消除重复。最后一种方式示例:

const TaxParcels = [{ PARCELID: 1},{ PARCELID: 2},{ PARCELID: 3}];
const TaxBills = [{ SBL20: 1},{ SBL20: 2},{ SBL20: 3}];
const CodeEnforcements = [{ SBL: 1},{ SBL: 2},{ SBL: 3}];

const final = [];
let count=0;

for (const TaxParcel of TaxParcels) {
  const ID = TaxParcel.PARCELID;

  const TaxBill = TaxBills.find(({ SBL20 }) => SBL20 === ID);
  const CodeEnforcement = CodeEnforcements.find(({ SBL }) => SBL === ID);

  if (TaxBill && CodeEnforcement) {
    count++;
    final.push({ ID,DETAILS: { TaxParcel,TaxBill,CodeEnforcement } });
  }
}

console.log(count);
console.log(JSON.stringify(final,null,'  '));

但也许最重要的改进是使用更合适的 id-keyed 结构,就像这里的其他答案一样。