6

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.

halfer
  • 19,824
  • 17
  • 99
  • 186
yigames
  • 185
  • 1
  • 5
  • 23

2 Answers2

2

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>
Rhumborl
  • 16,349
  • 4
  • 39
  • 45
  • While possibly more performant if you're performing a lot of queries (insofar as there are only `n+q` `toLowerCase` calls rather than `n*q` with my solution, where `n` is the number of terms and `q` is the number of queries), it should be noted that this solution does require twice the memory, which may be problematic if the term list is long. Also, Rhumborl, slight modification but I think OP is only trying to search 1 query at a time. I think they misspoke with calling `filter` an array. – 0x24a537r9 Jan 09 '15 at 09:50
  • Also, I think this would be more performant (constant lookup times) using an `object` with the lowercase terms as the keys pointing to arrays of the original strings they reference. You could also then optimize space requirements by replacing the value arrays for single, already-lowercase words a more compact type like `true` and just know how to interpret that. – 0x24a537r9 Jan 09 '15 at 09:55
1

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

0x24a537r9
  • 968
  • 1
  • 10
  • 24