M
M
Maxim2019-03-14 17:49:37
JavaScript
Maxim, 2019-03-14 17:49:37

How to speed up the search for a substring match?

$('input#searchVariant').on('keyup', function () {
            var query = this.value.toLowerCase();
            var variants = this.parentNode.nextElementSibling;
            var allVariants = variants.querySelectorAll('div.label-point');

            allVariants.forEach(function (item) {
                if (item.getAttribute('name').toLowerCase().indexOf(query) > -1) {
                    item.style.display = '';
                } else {
                    item.style.display = 'none';
                }
            })
        });

The above is an example of a currently running search. From the entire list, we hide those for which no matches were found. So, now this list is 2700 options and everything is very terribly slow. What can be the solution to this problem?

Answer the question

In order to leave comments, you need to log in

3 answer(s)
H
hzzzzl, 2019-03-14
@maximkv25

I propose to store allVariants in a variable in memory, and not as DOM elements, and draw everything you need when necessary through

$('input#searchVariant').on('keyup', function () { 
вычислить строку по которой искать,
найти нужные элементы в массиве/объекте с данными, 
сделать для каждого свой блок 
добавить куда надо на страницу 
}

A
Anton Anton, 2019-03-14
@Fragster

At a minimum , cache
var variants = this.parentNode.nextElementSibling;
var allVariants = variants.querySelectorAll('div.label-point');
Then remove .toLowerCase() (it is possible to cache the correspondence between the given name and the DOM tree element somewhere)
According to https://proglib.io/p/javascript-performance-mistakes , simple for is almost 8 times faster than forEach. Another from a series of savings on matches, replacing > with !==
You can use libraries for debounce (for example , https://lodash.com/docs/4.17.11#debounce ) so as not to call processing on each click, but, for example, not more often than once per second.
Well, read about the profiler in the development tools to find out which lines eat the most time. This is where you have to start.
I also thought that you can compare the previous and new input values, and if the new one is more strict (Abyr -> Abyrv), then search not for all, but only for those found at the previous stage. + you need to check if there will be an effect if you do not change the visibility, if it should not change. It is possible that style recalculation still occurs even if we assign the same value to the styles as they are stored.
In general, display without pagination of thousands of elements is somehow strange. So the straight road is further into reactive frameworks, because it's much more direct there than working directly with the DOM. I prefer vue.

A
Andrey Tsvetkov, 2019-03-15
@yellow79

It's not the search that slows you down, but the DOM manipulations
. First, replace the comparison > -1 with a strict inequality.
Second, don't use style object manipulation, instead add/remove a class, without having to add/remove a class if it's already in the right state. That is, you need to add a check for the presence / absence of a class.
And thirdly, at the beginning of the function that is called on the "keyup" event, I would stick a check on which button was pressed, there are a number of buttons that make no sense to respond to, for example, punctuation and spaces, I'm sure you will find a couple more = )

<style>.hidden{display:none}</style>
<script>
allVariants.forEach(function (item) {
  if (item.getAttribute('name').toLowerCase().indexOf(query) !== -1) {
    if(item.classList.contains('hidden')){
      item.classList.remove('hidden')
    }
  }
  else {
    if(item.classList.contains('hidden') === false){
       item.classList.add('hidden')
    }
  }
})
</script>

Well, as mentioned above, it’s probably worth abandoning forEach, I haven’t personally researched it myself, but it seems to me that creating a context for calling a function and calling it will be slower than going through the usual handicap

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question