Optimizing search of array of objects

Viewed 828

I have an array of objects that is a length of 5,866 like formatted like this {label: "Luke Skywalker", value: "556534"} and I am searching the objects and filtering by their label like so

  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 is the value that is being types in to filter. Before I was working with less than 1,000 entries initially and now with the user_list being 5,866 causes performance issues with the way I am filtering. I want to filter the data real-time when the user types.

2 Answers

I can think of 2 ways to optimize your searching function :

Using includes instead of indexOf, wich does not return an index, but only true/false

this.state.raw_user_list.filter(user => user.label.toLowerCase().includes(e.target.value.toLowerCase()))

According to this stack overflow answer, a Regex would be a lot faster (for Chrome in particular) :

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

Using the 'i' option in your Regex means that it is case insensitive


UPDATE

According to these tests, your function can be even faster than the previous one with a cached Regex :

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