使用 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
值非常独特,没有太多重复项。)
你说你只需要总和,而不是过滤产品的列表,所以我们可以稍微减少那个时间,但可能不会很多,通过:
- 通过不生成我们不需要的数组来减少内存流失量
- 当我们只需要一次时,不通过
products
两次。
- 避免函数调用(尽管函数调用在 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 (...)
部分与将它们放在外面,但我倾向于认为外面只是稍微快一点(因为 let
在 for
循环中的工作方式)。
最后,您可以将其与使用本机(不是 lodash)forEach
和 some
方法而不是 for
循环进行比较。
有什么方法可以比下面的方法更快地找到数组中的部分字符串吗?
这是我的示例数据:
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
值非常独特,没有太多重复项。)
你说你只需要总和,而不是过滤产品的列表,所以我们可以稍微减少那个时间,但可能不会很多,通过:
- 通过不生成我们不需要的数组来减少内存流失量
- 当我们只需要一次时,不通过
products
两次。 - 避免函数调用(尽管函数调用在 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 (...)
部分与将它们放在外面,但我倾向于认为外面只是稍微快一点(因为 let
在 for
循环中的工作方式)。
最后,您可以将其与使用本机(不是 lodash)forEach
和 some
方法而不是 for
循环进行比较。