What is the highest performance way to filter a list of JSON objects in JavaScript?

后端 未结 4 1411
感动是毒
感动是毒 2020-12-25 13:45

Let\'s assume I have a huge (1000+) list of objects like this:

[{name: \'john dow\', age: 38, gender:\'m\'}, {name: \'jane dow\', age: 18, gender:\'f\'}, ..]         


        
相关标签:
4条回答
  • 2020-12-25 14:04

    From experience, the following algorithm works quite well:

    1. When the user types the first letter, you perform a search using Array.filter() perhaps and store that result under whatever the user types (e.g. "j");

    2. When the user types another letter (e.g. "o"), you perform the search on whatever was typed before ("j"), reducing the number of items to go through

    3. When the user deletes one or more characters you try to find the stored searches based on whatever is left in the search box; if all fails, you show an empty list and invalidate the previously stored searches.

    0 讨论(0)
  • 2020-12-25 14:18

    From simple to more complex (no additional libs):

    1. Limit search for minimum x chars (usually 3 is acceptable)
    2. Delay the filtering while the user is typing using timeout:
    //clear previous timed filtering
    if (typingTimeout) {
          clearTimeout(typingTimeout);
          typingTimeout = null;
        }
    //schedule new filtering
    typingTimeout = setTimeout(() => {
       // do some filtering
    }, 2000); //acceptable 1-2s
    
    1. If you still wish for faster filtering, You can group your list alphabetically in an object:
    {
       A: ['Aron', 'Arnold', ...],
       B: ['Baby'],
       ....
    }
    

    Then filter them using the prefixed lists with the first char entered. It is just an example, you should group your data as you see fit (maybe first 2 letters...).

    Here is a function that I implemented to help prefix my array:

    export function prefixStringsArray(arr, prefixLength) {
      const prefixArr = arr.map((s) => s.substr(0, prefixLength));
      const filter = (item, query) =>
        item.toLowerCase().startsWith(query.toLowerCase());
    
      const prefixObj = {};
      for (const pre of prefixArr) {
        prefixObj[pre] = arr.filter((item) => filter(item, pre));
      }
    
      return prefixObj;
    }
    

    You should know that using JS object is a very good bet because they are accessed in O(1) (it is sort of a hash map) and if you group your data optimally you'll get small arrays to filter.

    Notes:

    1. If you choose to prefix your array you should watch out for the user searching query.length < prefixLength
    2. This gave me great results in mobile development (React native)
    3. The code is only a draft - manually tested
    0 讨论(0)
  • 2020-12-25 14:24

    Although a substring index (such as a Suffix tree) would make this faster, the direct search would be:

    function (s, l) {
        return l.filter(function (v) {
            return v.name.find(s) !== -1;
        });
    }
    

    where s is the query string and l is the list of objects.

    0 讨论(0)
  • 2020-12-25 14:26

    I wouldn't worry too much about performance in this case. A desktop computer should eat up 1000, or 10,000 evaluations without sweat. I would avoid any kind of complex optimisation because the risk of breaking functionality is probably higher than the benefit of slightly efficient processing.

    Javascript (ECMAScript 5) does provide new methods for filtering arrays. As a native method it is supposed to be a little faster.

    var regex = ...
    
    results = json.filter(function(result) {
       return regex.test(result.name)
    }
    

    Array.prototype.filter is supported in modern browsers, see http://kangax.github.com/es5-compat-table/. A patch for older browsers is can be added with this: https://github.com/kriskowal/es5-shim

    0 讨论(0)
提交回复
热议问题