1

I have an array of about 950 objects, each containing basic information about soccer players for me to list on the page. I'm adding search functionality to this wherein I check the "name" key in each object and return similar results. This code snippet assumes I have an empty array for the results (results = []), and obvs I'm looping using underscore (see: lodash):

_.each(players, function(player, i){

  if(player.name.search(searchString) !== -1){
    results.push(item);
  }

})

This works well, but takes FOREVER. Okay it actually takes about 1 second but it more or less destroys the browser and eats memory like chocolate cake while it's running and is a very sluggish UX.

The ask: Is there a better way to do this (better == quicker)?

I can put my actual data in a jsfiddle/jsbin/jswhatever if that helps.

trickford
  • 33
  • 5
  • filter might run slightly faster than each because it avoids an extra closure to the new collection... that function body would be "return player.name.search(searchString) !== -1;" also, if searchString is not a RegExp, indexOf() is usually faster than search(). if you posted the data we could test suggestions before offering them... – dandavis May 25 '14 at 18:02
  • I would suggest combining methods from these 2 answers: http://stackoverflow.com/questions/5349425/whats-the-fastest-way-to-loop-through-an-array-in-javascript and http://stackoverflow.com/questions/5296268/fastest-way-to-check-a-string-contain-another-substring-in-javascript – UKatz May 25 '14 at 18:11
  • I would guess that search() (uses regex) is the culprit, but you should be able to check for yourself using the profiler built into every browser. I often loop over large (5-20k) lists in js and it usually runs very very fast. – goat May 25 '14 at 18:11
  • Good point, @dandavis - hadn't thought of using indexOf instead of search, but that does seem to speed things up! – trickford May 25 '14 at 18:19
  • indexOf of is not the best way of searching: http://jsperf.com/search-indexof-in-read-property – jslayer May 25 '14 at 18:21
  • @jslayer: will that hit partial matches like indexOf does? – dandavis May 25 '14 at 18:22
  • @dandavis, I'm not sure. In this case, if data changes is not often and the name have a length limit, it would be interesting try to use one big string of names, where each name will take specific part (for example 32 chars) & recursive [String].indexOf searching through the full string. Surely without library functions & extra closures - just javascript. – jslayer May 25 '14 at 18:41

2 Answers2

0

Really not sure about performance, but I would imagine that _.filter would better suited for your issue.

var results = _.filter(players, function(player){
  return player.name.toLowerCase().indexOf(searchString.toLowerCase()) !== -1;
});
Joe
  • 2,596
  • 2
  • 14
  • 11
  • why lowerCase the search string 950 times? players.filter(function(player){ return player.name.toLowerCase().indexOf(this) !== -1; },searchString.toLowerCase()); avoids that – dandavis May 25 '14 at 18:11
0
  • You can find out whether the search-function is faster or slower than other 'checks' like indexOf or whatever.

  • What you can do is to have the players array sorted by the name-property already. Then you can go through the array alphabetically and skip the ranges of letters that do not match the first letter of your search term. That way you have some sort of indexing.

sjkm
  • 3,887
  • 2
  • 25
  • 43