【问题标题】:Best performance operations for JS Array NEQ operationJS Array NEQ 操作的最佳性能操作
【发布时间】:2021-08-28 09:23:33
【问题描述】:

我目前正在处理组合两个数组的优化问题。问题如下:

  • 我有 2 个不同大小的数组,其中数组 A 在所有情况下都比数组 B 小(大多数情况下大小不同)
  • 数组 A 包含具有两个 ID 的对象
[{
    AccountID: "1234141",
    ContactID: "1256612"
},{
    AccountID: "2346278",
    ContactID: "2378898"
}, ...]
  • 数组 B 包含具有简单键值对的对象。每个对象也有一个或两个包含在数组 A 中的 ID
[{
    AccountID: "1234141",
    Name: "Peter Peterson",
    Contact: "Mail",
    ...
  },
  {
    ContactID: "2378898",
    Name: "Max Mustermann",
    Contact: "Phone",
    ...
  },
  ...
]
  • 在执行算法之前,应该用作比较的 ID 字段的名称是已知的(例如 AccountID、ContactID)。 在代码示例中,此参数称为“idKeyName”
  • 该算法应计算两个数组上的 Not Equal 运算符。因此,它应该返回 Array B 而不包含 Array A 中在上面指定的字段中具有相同 ID 的元素。

旧代码是这样的:

jQuery.each(arrayA, function (index, value, array) {
    if (arrayA[index][idKeyName] !== "" && list.indexOf(arrayA[index][
            idKeyName
        ]) === -1)
        list.push(arrayA[index][idKeyName]);
});

jQuery.each(arrayB, function (index, value, array) {
    if (list.indexOf(arrayB[index][idKeyName]) === -1) {
        results.push(value);
    }
});

如您所见,由于阵列必须运行两次,因此性能非常差。
我对代码的改进导致我这样做:

arrayA.forEach(function (oItem) {
    var iIndex = arrayB.findIndex(function (x) {
        return oItem[idKeyName] === x[idKeyName];
    });
    if (iIndex !== -1) {
        arrayB.splice(iIndex, 1);
    }
});

由于 ArrayA 小于 ArrayB 我通过它而不是例​​如过滤 ArrayB,希望重复次数最少。如果我发现当前元素连接到 ArrayB 中的一个元素(相同的 ID),我将它从 ArrayB 中拼接出来。最后我只需要返回 ArrayB 作为结果。

问题:是否有更好(性能更快)的方法在两个阵列上计算此 NEQ 运算符?

感谢您的帮助!

【问题讨论】:

    标签: javascript arrays algorithm performance filter


    【解决方案1】:

    这两种解决方案的问题是需要为数组B 中的每个项目迭代数组A

    而是从第一个数组 (A) 相关 id 创建一个 Set,然后通过检查相关 id 未出现在 Set 中来过滤第二个数组 (b):

    const fn = key => (arrA, arrB) => {
      const arrASet = new Set(A.map(o => o[key]))
      
      return arrB.filter(o => !arrASet.has(o[key]))
    }
    
    const A = [{"AccountID":"1234141","ContactID":"1256612"},{"AccountID":"2346278","ContactID":"2378898"}]
    const B = [{"AccountID":"1234141","Name":"Peter Peterson","Contact":"Mail"},{"ContactID":"2378898","Name":"Max Mustermann","Contact":"Phone"}]
    
    const filterByAccountID = fn('AccountID')
    const filterByContactID = fn('ContactID')
    
    console.log(filterByAccountID(A, B))
    console.log(filterByContactID(A, B))

    【讨论】:

    • 感谢您的帮助!我可以将传统方法的时间从 42 秒减少到 266 毫秒。
    • 我已经更新了答案。我们实际上不需要对象,只需要 id,因此您可以使用 Set。它可能不会更快,但内存使用量更少。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-31
    • 2012-09-01
    • 2015-11-28
    相关资源
    最近更新 更多