0

I have an array of classes on element A and I would like to match those classes against an array, B. The classList array will always be longer than filters by a varying amount. For this reason, I believe that this is not a duplicate of this question.

I would like to do the following:

if( all elements of array B are present in array A ) {
    Add this element to elsIn;
} else {
    Add this element to elsOut;
}

I have tried following the answer in this SO Question, but it's not too helpful to me.

I know that jQuery offer a $.inArray function, but this would mean that I would need multiple loops to achieve my outcome and would be inefficient.

I have also found this question and answer however the JS code matched only against one element in an array instead of all elements.

var elsOut = [],
  elsIn = [],
  filters = [],
  classList;
$(document).on('click', '[data-filter]', function(e) {

  if ($(this).hasClass('is-active')) {
    filters.pop($(this).data('filter'));
  } else {
    filters.push($(this).data('filter'));
  }

  $('.trainer').each(function() {
    classList = this.className.split(' ');
    if (classList.contains(filters)) { // if all elements in "filters" match an element in "classList"
      elsIn.push(this);
    } else {
      elsOut.push(this);
    }
  });


  $(this).toggleClass('is-active');

  $(elsOut).fadeOut();
  $(elsIn).fadeIn();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
E.Owen
  • 653
  • 1
  • 8
  • 23
  • Possible duplicate of [How to know if two arrays have the same values](https://stackoverflow.com/questions/6229197/how-to-know-if-two-arrays-have-the-same-values) – Heretic Monkey Apr 22 '19 at 14:01
  • 1
    FYI: a shortcut for `classList = this.className.split(' '); if (classList.contains(filters))` is `if (this.classList.contains(filters))` - because elements have a `classList` property now (since like 2010) – Jaromanda X Apr 22 '19 at 14:03
  • @HereticMonkey Thanks for pointing me to this question! I think it is along the right lines but my arrays won't be equal. One will nearly always be longer than the other, meaning that `if (arr1[i] !== arr2[i])` will nearly always return false. – E.Owen Apr 22 '19 at 14:04
  • 1
    Okay, how about [Check if every element in one array is in a second array](https://stackoverflow.com/q/8628059/215552)? – Heretic Monkey Apr 22 '19 at 14:15
  • You have a typo in your code: `elsOut.pust(this);` should be `elsOut.push(this);`? – BugsArePeopleToo Apr 22 '19 at 14:29
  • @HereticMonkey I've posted an answer to my question based on that second link. Thanks for pointing that out to me! – E.Owen Apr 22 '19 at 14:58

2 Answers2

0

You can use Set and set size check. For example:

const arrA = [1, 2, 3, 4, 5],
      arrB = [2, 3],
      set  = new Set([...arrA, ...arrB]);

if (set.size === arrA.length) {
  // all elements of array B are present in array A
} else { 

}
Stas Amasev
  • 319
  • 1
  • 3
  • 8
0

Borrowing some help from the answer to this question, and a little more inspiration from this question, I've conjured up the following solution. Thanks to @HereticMonkey for pointing me in the right direction!

function contains(haystack, needles) {
  haystack.sort();
  needles.sort();
  var i, j;
  for (i = 0, j = 0; i < haystack.length && j < needles.length;) {
    if (haystack[i] < needles[j]) {
      ++i;
    } else if (haystack[i] == needles[j]) {
      ++i;
      ++j;
    } else {
      // needles[j] not in haystack
      return false;
    }
  }
  // make sure there are no elements left in needles
  return j == needles.length;
}

function removeA(arr) {
  var what, a = arguments,
    L = a.length,
    ax;
  while (L > 1 && arr.length) {
    what = a[--L];
    while ((ax = arr.indexOf(what)) !== -1) {
      arr.splice(ax, 1);
    }
  }
  return arr;
}

var filters = [];

$(document).on('click', '[data-filter]', function(e) {
  e.preventDefault();

  var elsOut = [],
    elsIn = [],
    classList;

  if ($(this).hasClass('is-active')) {
    removeA(filters, $(this).data('filter'));
  } else {
    filters.push($(this).data('filter'));
  }

  $('.trainer').each(function() {
    classList = this.className.split(' ');
    if (contains(classList, filters)) { // if all elements in "filters" match an element in "classList"
      elsIn.push(this);
    } else {
      elsOut.push(this);
    }
  });

  $(this).toggleClass('is-active');

  $(elsOut).fadeOut();
  $(elsIn).fadeIn();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
E.Owen
  • 653
  • 1
  • 8
  • 23