优化对象数组的搜索

3

我有一个由对象组成的数组,长度为5866,格式如下:{label: "Luke Skywalker", value: "556534"},我正在按照标签搜索并过滤这些对象,如下:

  onChange = (e) => {
        e.persist()
         this.setState({filter:e.target.value, filtered_array: 
            this.state.raw_user_list.filter(user =>
              user.label.toLowerCase().indexOf(e.target.value.toLowerCase()) > -1)})
    }

...
     <form style={{paddingBottom:'10px'}}>
              Filter: <input name="filter" value={this.state.filter} onChange={this.onChange} type="text" style={{
                border: '1px solid #cccccc',
              }}/>
            </form>

this.state.filter 是正在输入筛选条件的值。 在最初我处理少于1,000个条目时没有问题,但现在使用 user_list 的 5,866个条目会导致性能问题。我希望实现实时数据筛选,当用户输入时进行筛选。


3
不要在每次迭代时执行 e.target.value.toLowerCase(),将其存储在作用域变量中,并从迭代函数中引用它。这是一个简单的修复方法,应该可以立即看到效果。 - Patrick Roberts
除了将lowerCase外部化(您每次循环都在重复它),如果允许,您可以考虑使用一些外部库。在这种情况下,Fuse.js似乎是您的好朋友:https://github.com/krisk/Fuse - briosheje
3
问题更可能与您的使用方式有关。5900个元素并不算很多。 - charlietfl
1
如果onChange与连续输入有关,一些限流会有所帮助。 - charlietfl
此外,如果当前筛选器包含先前的筛选器,则当前结果是filtered_array的子集,您无需再次对整个raw_user_list进行筛选。 - Thomas
显示剩余3条评论
2个回答

1

1
我可以想到两种优化搜索功能的方法:
1. 使用 `includes` 替代 `indexOf`,`includes` 只返回 true/false 而不是索引值。
2. ......(后面部分没有提供需要翻译的内容)
this.state.raw_user_list.filter(user => user.label.toLowerCase().includes(e.target.value.toLowerCase()))

根据 这个Stack Overflow回答,正则表达式会更快一些(特别是对于Chrome浏览器):
this.state.raw_user_list.filter(user => user.label.match(new RegExp(e.target.value, 'i')))

在正则表达式中使用“i”选项意味着它是不区分大小写的。

更新

根据这些测试,您的函数使用缓存的正则表达式可以比之前的更快:

const rValue = new RegExp(e.target.value, 'i')
this.state.raw_user_list.filter(user => rValue.test(user.label))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接