Javascript 数组筛选器-除去O(n^2)

Javascript 数组筛选器-除去O(n^2),javascript,arrays,filter,Javascript,Arrays,Filter,我需要对非常大的对象数组(超过200k个元素)执行2个过滤器,所以我希望我的代码在javascript中尽可能快 第一个过滤器很简单,因为我只需要删除空的元素(null): 第二个过滤器是检查validArr[i].name是否等于其他数组中的一个元素。目前我是这样做的: for(let i = 0, l = validArr.length; i < l; i++) { if (findInArray(validArr[i].name, otherArr)) { f

我需要对非常大的对象数组(超过200k个元素)执行2个过滤器,所以我希望我的代码在javascript中尽可能快

第一个过滤器很简单,因为我只需要删除空的元素(null):

第二个过滤器是检查
validArr[i].name
是否等于其他数组中的一个元素。目前我是这样做的:

for(let i = 0, l = validArr.length; i < l; i++) {
    if (findInArray(validArr[i].name, otherArr)) {
        finalArr.push({
            name: validNpc[i].nick,
            id: validNpc[i].id
        });
    }
}

const findInArray = (val, arr) => {
    for(let i = 0, l = arr.length; i < l; i++) {
        if(arr[i] === val) return true;
    }
    return false;
};
for(设i=0,l=validArr.length;i{
for(设i=0,l=arr.length;i

在循环中,我进行了微优化,但有O(n^2),我想重构,但不知道如何重构。

将otherArr转化为一个集合,然后查找需要O(1),整个循环是O(n):


您可以使用时间复杂度为O(1)的
Set
has
方法

otherArr = new Set(otherArr);
for(let i = 0, l = validArr.length; i < l; i++) {
    if (findInArray(validArr[i].name, otherArr)) {
        finalArr.push({
            name: validNpc[i].nick,
            id: validNpc[i].id
        });
    }
}

const findInArray = (val, arr) => {
    return arr.has(val)
};

一些示例数据会很有帮助,请添加它。
validArr
“name”属性中的值到底是什么?如果它们是字符串,则可以将
otherArr
转换为一个简单对象,将“name”值作为属性名,将类似
true
1
的值作为属性名。然后您可以只进行一次简单的属性查找。@Pointy或使用@melpomene是的;我没有做那么多,因为在我的个人世界里,我主要使用ES5,但它会更好。否则就是字符串数组,你没有真正使用
reduce
来建立一个值。您只是使用它来获得在数组上迭代的副作用。同样的代码可以用
filter
map
forEach
来编写@melpomene我明白你的意思了。我用
forEach
解决方案进行了更新。谢谢你现在当我想到它时,我还需要第三个过滤器,很抱歉我没有提到它,请给我一分钟时间,我将编辑我的问题。那么构造函数(
new Set(otherArr)
)呢,它是线性的吗?我找不到信息。@mbojko是的,它必须是。我检查了jsperf集合vs loop,它显示loop更快。。。但仅适用于元素数量低于200的数组。你的例子是线性的吗?
方法如何知道它在集合中包含值而不在其上循环?@bt101是的,时间复杂度仅为较大的数据集提供了一个很好的度量。正如你所说,200个元素或更多元素会更好。在映射上创建/插入/查找是O(1),但这些操作仍然代价高昂。只有当n增长时,你才能得到它的好处。你应该读一下
  const names = new Set(otherArr);

  const result = validArr
    .filter(it => names.has(it.name))
    .map(({ nick, id }) => ({ name: nick, id }));
otherArr = new Set(otherArr);
for(let i = 0, l = validArr.length; i < l; i++) {
    if (findInArray(validArr[i].name, otherArr)) {
        finalArr.push({
            name: validNpc[i].nick,
            id: validNpc[i].id
        });
    }
}

const findInArray = (val, arr) => {
    return arr.has(val)
};
otherArr = new Set(otherArr)
const finalArr = [];
validArr.forEach(x => {
    if(otherArr.has(x.name)){
       finalArr.push({ name:x.nick, id:x.id })
    }
})