3

What I am trying to do is if I have Array a = {1,2,3,4}; b = {1,2};

Then I want subset array as c = {3,4};

Can anybody help me?

1
  • 1
    Please clarify your terminology. In your example c is indeed a subset of a, but you have not indicated why that's the particular subset you want. Did you perhaps been the relative complement of b in a, i.e. b \ a? en.wikipedia.org/wiki/Set_%28mathematics%29#Complements Commented Sep 24, 2010 at 7:59

4 Answers 4

6
a = [1, 2, 3, 4]
b = [2, 1, 5]

comp = a.filter(function(e) { return b.indexOf(e) < 0 })

see Array.filter and Array.indexOf for more details and degradation options.

Sign up to request clarification or add additional context in comments.

Comments

3

I'm not aware of any built-in way to do this, you basically have to loop through c and check whether each element is in a and, if so, remove it. The Array#indexOf method can help you with checking, but not all implementations have it (though most do). Removal can be via Array#splice.

So:

var a, c, index;
a = [1, 2];
c = [1, 2, 3, 4];
for (index = c.length - 1; index >= 0; --index) {
    if (a.indexOf(c[index]) >= 0) {
        c.splice(index, 1);
    }
}

...and then either supply your own implementation of Array#indexOf if your environment doesn't support it, or use a library like Prototype that supplies it for you (jQuery gives it to you as well, but through its own jQuery.inArray function). If doing it yourself:

if (!Array.prototype.indexOf) {
  (function() {
    Array.prototype.indexOf = Array_indexOf;
    function Array_indexOf(elm) {
      var index;
      for (index = 0; index < this.length; ++index) {
        if (this[index] === elm) {
          return index;
        }
      }
      return -1;
    }
  })();
}

Note that adding to the Array prototype as above can be dangerous when done with poorly-written code code that makes assumptions about the environment. Specifically, code that treats for..in as though it loops through array element indexes (it doesn't, it looks through object property names) will get messed up if you add to the Array prototype. (That's probably why jQuery doesn't do it.)

Live example

7 Comments

Why did you put the definition of indexOf in a closure instead of like: if (!Array.prototype.indexOf) { Array.prototype.indexOf = function(elm) {...};}; ?
@thomasmalt: Because I like functions to have names, and unfortunately that's the only way that's compatible with IE (JScript) to give the function a name without creating a global symbol and without creating the function if we don't have to: blog.niftysnippets.org/2010/03/anonymouses-anonymous.html Your way is great other than the function not having a name.
Thanks. I normally prefer to extend by assigning anonymous functions to variables. For me that enhances readability and makes it easy to create well formatted, well documented, source code. :)
@thomasmalt: Fair enough. I like to have function names in my call stack when using a debugger. :-) Hopefully, someday, Microsoft will fix the JScript bug that prevents just using a named function expression like Array.prototype.indexOf = function Array_indexOf() { ... }. But sadly, not even JScript 6 (IE8) fixes it: jsbin.com/alexe3/2 Maybe IE9, they're doing a lot of standards work...
And debugging is a really good reason to use named functions. Thanks for the tip.
|
3

Assuming that you're after the relative complement of b in a.

function complement(a, b) {

  // convert A to an associative array
  var myHash = {};
  for (var i = 0; i < a.length; ++i) {
    myHash[a[i]] = 1;
  }

  // remove the elements that exist in B
  for (var i = 0; i < b.length; ++i) {
    delete myHash[b[i]];
  }

  // what's left is A \ B
  // assumes that no-one broke Array by adding new properties to the prototype
  return Object.keys(myHash);
}

// test
var a = [1, 2, 3, 4];
var b = [1, 2];
var c = complement(a, b);
alert(c);

This should scale well for larger arrays, since it uses hash table indexing rather than linear searches to remove the unwanted elements.

1 Comment

hash-based solutions don't work when (some of) array elements are Objects.
2

Here is another solution which uses Array.filter() and Array.includes()

function arrayDifference(a, b) {
  return a.filter((x) => !b.includes(x));
}

const a = [1, 2, 2, 2, 3, 4]
const b = [1, 2]

arrayDifference(a,b) // returns [3, 4]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.