在使用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);
一切都运行得很好,但如果我必须处理大约300k个元素和100k个关键字,大约需要3分钟才能找到这个查询。有什么办法可以缩短这段时间吗?(product
值非常唯一,没有太多重复项。)
解决方案
您说过您只需要总和,而不是筛选出的产品列表,因此我们可以将该时间略微减少,但可能不会大幅减少:
- 通过不生成我们不需要的数组来减少内存颠覆量
- 当我们只需要一次时,不要进行两次通过
products
。 - 避免函数调用(尽管函数调用在JavaScript引擎中)
所以:
let sum = 0;
for (const {product, price} of products) {
for (const keyword of keywords) {
if (product.includes(keyword)) {
sum += price;
break;
}
}
}
使用新的(Ish)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 (...)
部分内与将它们放在for (...)
部分外进行试验,但我倾向于认为在外部只会稍微快一点(因为let
在for
循环中的工作方式)。
最后,您可以将其与使用本机(而不是lowash)forEach
和some
方法而不是for
循环进行比较。
相关文章