使用 lodash 在带有过滤器的数组中查找部分字符串的最快方法是什么?

What is the fastest way to find partial string in arrays with filter using lodash?

有什么方法可以比下面的方法更快地找到数组中的部分字符串吗?

这是我的示例数据:

const products = [
  {
    "product": "test1",
    "price": 11
  },
  {
    "product": "test2",
    "price": 31
  },
  {
    "product": "xxxx",
    "price": 21
  },
  {
    "product": "ssss",
    "price": 22
  },
]

这是我的关键字(但实际上还有很多):

const keywords = [ "test", "xx" ]

我想用关键字过滤产品然后对所有产品价格求和我的输出应该是

63

这是我尝试做的事情:我首先过滤我的产品,我使用 indexOf 因为它比 includes 快:

const fil = _.filter(products, (product) => {
    return _.some(keywords, (v) => product.name.indexOf(v) >= 0 );
});

然后我用 reduce:

对它们求和
const sum = fil.reduce(function (sum, data) {
    return sum + data.price;
}, 0);

一切正常,但如果我必须处理大约 30 万个元素和 10 万个关键字,则需要大约 3 分钟才能找到此查询。有什么办法可以减少那个时间吗? (product 值非常独特,没有太多重复项。)

你说你只需要总和,而不是过滤产品的列表,所以我们可以稍微减少那个时间,但可能不会很多,通过:

  1. 通过不生成我们不需要的数组来减少内存流失量
  2. 当我们只需要一次时,不通过 products 两次。
  3. 避免函数调用(尽管函数调用在 JavaScript 引擎中 快速

所以:

let sum = 0;
for (const {product, price} of products) {
    for (const keyword of keywords) {
        if (product.includes(keyword)) {
            sum += price;
            break;
        }
    }
}

使用新的(大概)for-of 循环。然而,在幕后,for-of 涉及函数调用和创建对象(尽管在遍历本机数组时,JavaScript 引擎可能能够完全优化这些)。你可能想在经典的 for 循环中尝试一下,看看哪个能给你最好的速度:

let sum = 0;
let productsLength = products.length;
let keywordsLength = keywords.length;
let pIndex, kIndex;
for (pIndex = 0; pIndex < productsLength; ++pIndex) {
    const {product, price} = products[pIndex];
    for (kIndex = 0; kIndex < keywordsLength; ++kIndex) {
        if (product.includes(keywords[kIndex])) {
            sum += price;
            break;
        }
    }
}

同样,尝试将循环变量 放在 for (...) 部分与将它们放在外面,但我倾向于认为外面只是稍微快一点(因为 letfor 循环中的工作方式)。

最后,您可以将其与使用本机(不是 lodash)forEachsome 方法而不是 for 循环进行比较。