Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use _.where() in underscore to compare values regardless of case

I have a webpage where if something typed in search box it then iterates through a file for that value. I need it so that search/find not case sensitive. The case sensitivity must remain in the file but for comparison purposes it disregards the case.

So currently I am using underscore command:

arr=_.where(arr,filter);

but the 2 arrays arr and filter - I need them to be compared/used regardless of case so the end result arr contains results which will mixture of upper and lower case but matches value(s) in arr.

like image 791
yigames Avatar asked Jan 09 '15 09:01

yigames


2 Answers

Try using filter instead:

var filter = ["Apple", "bANAna", "orange"];
var arr = ["apPle", "ORANGE"];

// make filter lower case once    
var filterLower = _.invoke(filter, "toLowerCase");

var arr2 = _.filter(arr, function(v) {
    // make entry lower case and see if it is in filterLower
    return _.contains(filterLower, v.toLowerCase());
});

console.dir(arr2);
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
like image 64
Rhumborl Avatar answered Oct 14 '22 10:10

Rhumborl


Unfortunately, JS is not great when it comes to internationalized case-insensitive string comparison. If you're just sticking to ASCII though, the solution is fairly straightforward (using filter though, not where):

function getMatches(query, arr) {
  var lowerQuery = query.toLowerCase();
  return _.filter(arr, function(term) {
    return term.toLowerCase() == lowerQuery;
  });
}

Or if you want to precompute everything because you expect to make a lot of queries in the same JS session:

var index = _.groupBy(arr, function(term) { return term.toLowerCase(); });

// Post-process index to reduce memory footprint by turning redundant values to nulls
// (which take up less memory than arrays with a string in them).
index = _.object(_.map(index, function(terms, key) {
  return [key, (terms.length == 1 && terms[0].toLowerCase() == terms[0] ? null : terms)];
}));

function getMatches(query) {
  var lowerQuery = query.toLowerCase();
  return (lowerQuery in index ? index[lowerQuery] || lowerQuery : []);
}

This second method has the advantage of only computing toLowercase() the minimal number of times and minimal data storage because of the post-processing step.

Here's a JSFiddle for both

like image 24
0x24a537r9 Avatar answered Oct 14 '22 11:10

0x24a537r9