1

Is there i way in JavaScript to compare two arrays;

This is my example.

array1 = ['jpg','png'];

array 2 = ['jpg','pdf','png','bmp'];

I my case i need if are all elements of array1 part of array2 return TRUE, or something. In case only one element of array 1 match, element in array 2 return FALSE. Order its not important. Basciclly this is validation of uploaded files, i try to removing button, if two file are not with right extension.

I try function inarray, but i think it only works with string not array

Vladimir Štus
  • 217
  • 3
  • 16
  • `array1` compared to `array2` return `true` and `array2` compared to `array1` return `false`? – Bharadwaj Dec 29 '14 at 13:18
  • I heard somewhere that you can just compare the `toString` of each array. – Mr. Polywhirl Dec 29 '14 at 13:20
  • 2
    I don't think this is a duplicate of [Comparing two arrays in Javascript](http://stackoverflow.com/questions/7837456/comparing-two-arrays-in-javascript). This question asks how to test if `array1` is a subset of `array2` where order doesn't matter, which seems quite different from testing the equality of two arrays. I'm not 100% sure if this is a *good* question (maybe it's too specific to be helpful to any likely future readers? maybe not?), but it's not a duplicate. – apsillers Dec 29 '14 at 13:24
  • This is not duplicated at all. But it's already closed, so whatever. @Vladimir Štus here is an answer with proper validation http://jsfiddle.net/wxfnr2f2/. Also check loxxy's answer for another working solution for your problem. – dfsq Dec 29 '14 at 13:26

3 Answers3

2

If legacy is not a problem, Something like this would do:

var array1 = ['jpg','png','d'];
var array2 = ['jpg','pdf','png','bmp'];

var result = !array1.filter(function(a) { return array2.indexOf(a)==-1; }).length;   

// result is False
loxxy
  • 12,990
  • 2
  • 25
  • 56
  • OP wants to check **all elements** are there, `intersection.length === array1.length` – Paul S. Dec 29 '14 at 13:24
  • @PaulS. The code in this answer appears to be behave correctly. It *eliminates* items that *are* a match and tests for any remaining non-match items in `array1` (thus a non-zero length is a failure condition, implying that something wasn't eliminated as a match). – apsillers Dec 29 '14 at 13:28
  • This is correct although not optimal answer. No need to check further is something is already returned `-1`. – dfsq Dec 29 '14 at 13:32
  • 1
    Per @dfsq's suggestion, a better solution might be `array1.every(function(a) { return array2.indexOf(a)!=-1; })`, which will return `false` early on the first failure (and the use of `every` here seems more idiomatic to me than `filter`, but that's a bit nitpicky). – apsillers Dec 29 '14 at 13:33
  • 1
    @apsillers No, my suggestion was `!array1.some(function(el) { return array2.indexOf(el) == -1; });`, so it never checks further is something is already `-1`. – dfsq Dec 29 '14 at 13:35
  • @dfsq True, Valid Point.. But something tells me, that OP has a pretty small set, for this to matter at all. – loxxy Dec 29 '14 at 13:36
  • @dfsq Our solutions appear to be behaviorally identical `:)` I decided to put my `!` inside the callback; you prefer it outside. Both `some` and `every` perform early termination. – apsillers Dec 29 '14 at 13:44
  • so is it loxxy answer valid – Vladimir Štus Dec 29 '14 at 13:48
  • @VladimirŠtus Yup, it is. However, Close your eyes & pick one from the comments of apsillers or dsfq, if you are still worried about performance. – loxxy Dec 29 '14 at 13:57
0

if are all elements of array1 part of array2 return TRUE
only one element of array1 match, element in array2 return FALSE

You can think about this in two ways,

  • take the intersection and check the intersection is the same as the input
  • loop over the input and return false on the first mismatch

Here is an example of using a loop

var a = [1, 3],
    b = [1, 5],
    c = [0, 1, 2, 3, 4];

function test(needles, haystack) {
    var i;
    for (i = 0; i < needles.length; ++i) {
        if (haystack.indexOf(needles[i]) === -1) {
            return false;
        }
    }
    return true;
}

test(a, c); // true
test(b, c); // false
Paul S.
  • 64,864
  • 9
  • 122
  • 138
0

If the result of filtering the second array with the values of the first is an array with length equal to the length of the first array, the first array is a subset of the second. You can write a function for that, or assing an extra method to Array.prototype:

var array1 = ['jpg', 'png'];
var array2 = ['jpg', 'pdf', 'png', 'bmp'];
var array3 = ['jpg', 'bmp', 'pdf'];

Helpers.log2Screen('array1 subset of array2? ', 
                    isSubset(array1, array2) ? 'yes' : 'no' );

// assign and use Array.prototype.subsetOf
Array.prototype.subsetOf = isSubsetProto;
Helpers.log2Screen('array1 subset of array3? ', 
                    array1.subsetOf(array3) ? 'yes' : 'no' );

function isSubset(arr1, arr2) {
  return arr2.filter(
          function (v) {return arr1.indexOf(v) > -1; }
         ).length == arr1.length;
}

function isSubsetProto(arr) {
    return arr.filter(
          function (v) {return this.indexOf(v) > -1; }, this
         ).length == this.length;
}
<script src="http://kooiinc.github.io/JSHelpers/Helpers-min.js"></script>
KooiInc
  • 119,216
  • 31
  • 141
  • 177