1

I have an array of items that I'd like the user to be able to filter through in using multiple drop-down lists. In this case, each character for the strings has its own filter.

My question is how can I filter my array once it's already been filtered? i.e. my array, parts, ["35X", "45X" "35L"], if I've already filtered down to strings containing '3', how can I filter down to strings containing 3 and L?

    var parts = [" 35X", " 35L", " X44", " 55L", " 55X"];
    var obj8 = document.getElementById("selectOperators");
    var obj1 = document.getElementById("Series");

function getOption1() {
    var din = filterParts(obj1.options[obj1.selectedIndex].value)
    document.getElementById("other").innerHTML = din;
    }

function getOption8() {
    var ryan = filterParts(obj8.options[obj8.selectedIndex].value)
    document.getElementById("other").innerHTML = ryan;
    }

function filterParts(query) {
    return parts.filter((el) => el.toLowerCase().indexOf(query.toLowerCase()) > -1)
    } 

If possible to do so without the use of jquery

  • 1
    `parts.filter(part => /^3.*L$/.test(part))` is what you're going to want to do to filter based on "beginning with 3 and ending with L" – mhodges Jul 13 '17 at 15:26
  • You can filter in series like so: `arr1.filter(filterAfunc).filter(filterBfunc);` – frozen Jul 13 '17 at 15:27

2 Answers2

1

Array.prototype.filter returns an Array, so you can chain subsequent .filter calls to filter based on many predicates

const startsWith = s => x =>
  x.substr(0, s.length) === s
  
const endsWith = s => x =>
  x.substr(-s.length) === s
  
const data =
  ['35X', '45X', '35L']

const result =
  // chain filter calls, one after the next
  data.filter(startsWith('3')) // => [ '35X', '35L' ]
      .filter(endsWith('L'))   // => [ '35L' ]

console.log(result)
// [ '35L' ]

As you might suspect, chaining many .filter calls will create many intermediate array results and will iterate through each in a series. For large data sets, these intermediate results could be very expensive to create. If this is your case, I invite you to look at transducers – the concept is more complex than simple array filtering, but you don't have to understand how they work in order to use them.

Mulan
  • 129,518
  • 31
  • 228
  • 259
  • I think the way I had worded my question may have been slightly misleading to the answer I was looking for. I'd like to filter not actually by the starting/ending character (as my actual project contains 10+ character strings). I just edited the question to be a little clearer, my apologies. – Ryan Murray Jul 17 '17 at 12:07
-1

I recommend a recursive filter function

var arr, find, _findByQuery;

arr = [" 35X", " 35L", " X44", " 55L", " 55X"];

_findByQuery = function(query, a) {
  return a.filter(function(obj) {
    return obj.toLowerCase().indexOf(query) > -1;
  });
};

find = function(queries, a) {
  var q, rslt, _i, _len;
  rslt = a.slice();
  for (_i = 0, _len = queries.length; _i < _len; _i++) {
    q = queries[_i];
    rslt = _findByQuery(q, rslt);
  }
  return rslt;
};

Then you can chain as many queries as you wish like so:

find(['3', 'L'], arr) // ["35L"]

This doesn't necessarily care about the position of your individual queries as that would require a more in-depth UI to support filtering options.

jusopi
  • 6,791
  • 2
  • 33
  • 44