Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to achieve maximum efficiency with underscore's map and filter?

Is it possible to combine Underscore's filter and map? I currently have two separate function calls, but I'm wondering if I can make them more efficient by combining them into a single call, somehow.

Basically I have an array of country names - I want to filter them using a regex, then map the filtered results to an array of DataItem objects. This is my current code:

var filteredData = _.filter(allCountries, function(n, i){ 
  var re = RegExp("^" + searchString, "i");
  if (re.exec(n['country'].toLowerCase()) !== null) {
    return true;
  }
});
var mappedData = _.map(filteredData, function(n, i){ 
  return new DataItem(i, n['name'], n['budget']);
});

Any other tips for improved efficiency would also be gratefully received.

like image 604
Richard Avatar asked Mar 16 '12 14:03

Richard


2 Answers

Underscore offers a chaining ability through _.chain:

_.chain(allCountries)
 .filter(function(n, i) { ... })
 .map(function(n, i) { ... })
 .value(); // stop chaining and get the result

Instead of re.exec(...) !== null you can use re.test(...), and note that you need to escape special regexp characters for searchString.

In this simple case however, it's better to use .indexOf to check whether the string starts with a substring:

// substring should be apparent at position 0, discard case for both strings
return n.country.toLowerCase().indexOf(searchString.toLowerCase()) === 0;

For string literals, .foo may be clearer than ['foo'].

like image 62
pimvdb Avatar answered Oct 04 '22 23:10

pimvdb


You can use each instead:

 result = []
_.each(array, function(elem) {
    if(elem.indexOf(search) == 0)
        result.push(...whatever...)

Also note that you don't need a regular expression just to find out if a string starts with another one.

like image 39
georg Avatar answered Oct 04 '22 21:10

georg