¿Cómo hago coincidir este texto más rápido?

I'm building an autosuggest for names. When the user types in the textbox, it hits the server and runs this:

var names = [ list of 1000 names ]; //I have a list of 1000 names, this is static.
var query = 'alex';
var matched_names = [];

//This is when it gets slow....
names.forEach(function(name){
    if(name.indexOf(query) >= 0){
        matched_names.push(name);
    }
});

return matched_names;

How can I make this faster? I'm using Node.js

preguntado el 27 de agosto de 11 a las 22:08

note that your code is case sensitive: 'alex' will not match 'Alex'; this might be what you want, though. -

4 Respuestas

If the names are static then move this code to the client and run it there. The only reason to run code like this on the server is if the data source is dynamic in some way.

Doing this logic client-side will dramatically improve performance.

Respondido 28 ago 11, 02:08

Probablemente deberías usar filter instead, for one thing, because it's native:

var names = [ /* list of 1000 names */ ];
var query = 'alex';
var matched_names = names.filter(function(name) {
    return name.indexOf(query) > -1;
});
return matched_names;

Respondido 28 ago 11, 02:08

If you store the names in sorted order, then you can use binary search to find the region of names within the sorted order that start with the fragment of name that the user has typed so far, instead of checking all the names one by one.

On a system with a rather odd programming language, where I wanted to find all matches containing what the user had typed so far in any position, I got a satisfactory result for not much implementation effort by reviving http://en.wikipedia.org/wiki/Key_Word_in_Context. (Once at university I searched through a physical KWIC index, printed out from an IBM lineprinter, and then bound as a document for just this purpose.

Respondido 28 ago 11, 12:08

I would suggest you to do this stuff on the client-side and prefer (for now) a while loop instead of a filter/forEach approach:

var names = [ /* list of 1000 names */ ]
,   query = 'alex'
,   i = names.length
,   matched_names = [];

while(i--){
  if(names[i].indexOf(query) > -1){
    matched_names.push(names[i]);
  }
}

return matched_names;

This will be much faster (even if filter/forEach are natively supported). See this benchmark: http://jsperf.com/function-loops/4

Respondido 28 ago 11, 16:08

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.