views:

67

answers:

5

hi,

well, i have two arrays and want to remove in one of them, all elements which exist in the other as well.

  • is there a native JS possibility?
  • is there a jQuery functino?
  • what is best practice to do so (the faster the better)

thanks

p.s.: just post code in other languages too, maybe i can port it to javascript

Update, after accepting answere to help the JS dudes ;-)

// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
    var rest = this.slice((to || from) + 1 || this.length);
    this.length = from < 0 ? this.length + from : from;
    return this.push.apply(this, rest);
};
// Array Contains - By Helmuth Lammer (TU Vienna)
Array.prototype.contains = function(key){

    for(var i = 0; i<this.length; i++){
        if(this[i]  == key) return i;
    }

    return false;
}

(There is a native JS method named contains too, but it should work)

+1  A: 

Given two sets a and b, to remove all elements present in a from b. Translation to array formatting and javascript left as an exercise to the reader. Optimizations exist for sorted arrays.

for(element e : b) {
    if(a.contains(e)) {
         b.remove(e);
    }
}
glowcoder
well works not in JS with this syntax, but the idea is clear.i think it is not very fast. the contains() and the remove() methode have to run through all items each time ... or am i absolutely wrong?
helle
The idea was to take the pseudocode and apply to any language. The contains is necessary, and is O(n). The remove can be optimized by using a secondary structure (ArrayList-esque comes to mind) to build a new B array, and adding elements to it, rather than removing. Not being a Javascript guy, I don't know what mechanisms exist for such operations.
glowcoder
cool ! thanks - works.
helle
A: 

This may help.

mcandre
Answers should be more than just links.
tvanfosson
A: 

[See it in action]

// two arrays
var arr1 = [1,2,3,4,5];
var arr2 = [4,5,6,7,8];

// returns the element's index in an array
// or -1 if there isn't such an element
function indexOf( arr, el ) {
  for ( var i = arr.length; i--; ) {
    if ( arr[i] === el ) return i;
  }
  return -1;
}

// go through array1 and remove all
// elements which is also in array2
​for ( var i = arr1.length; i--; )​ {
  if ( indexOf( arr2, arr1[i] ) !== -1 ) {
    arr1.splice(i, 1);
  }
}

// result should be: arr1 = [1,2,3] 
alert( arr1 );
​
galambalazs
+1  A: 
var foo = [1, 2, 3, 4, 5];

function removeAll(a, b) {
    var i = 0,
        j;

    while (i < b.length) {
        for (j = 0; j < a.length; j++) {
            if (a[j] === b[i]) {
                b.splice(i, 1);
                i--;
                break;
            }
        }
        i++;
    }
}

removeAll([2, 4], foo);
// foo === [1, 3, 5]
lawnsea
A: 

I had to write a code once where an Ajax call would return an array containing a list of element which must be deleted from a local (client-side) array.

I ended implementing it this way:

// The filter method creates a new array with all elements that pass the
// test implemented by the provided function.
local_array = local_array.filter( function (element) {
    // Now I check if this element is present in the "delete" array. In order to do 
    // that I use the "some" method which runs a callback function for each of the
    // array elements and returns true or false.
    return !items_to_delete.some( function(item) {
        return item.pk === element.pk;
    });
});

Edit: In order to make it cross-browser (I am talking about IE here). You will have to define the some and filter functions. Just put this somewhere in your code:

if (!Array.prototype.some)
{
  Array.prototype.some = function(fun /*, thisp*/)
  {
    var i = 0,
        len = this.length >>> 0;

    if (typeof fun != "function")
      throw new TypeError();

    var thisp = arguments[1];
    for (; i < len; i++)
    {
      if (i in this &&
          fun.call(thisp, this[i], i, this))
        return true;
    }

    return false;
  };
}

if (!Array.prototype.filter)
{
  Array.prototype.filter = function(fun /*, thisp*/)
  {
    var len = this.length >>> 0;
    if (typeof fun != "function")
      throw new TypeError();

    var res = [];
    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in this)
      {
        var val = this[i]; // in case fun mutates this
        if (fun.call(thisp, val, i, this))
          res.push(val);
      }
    }

    return res;
  };
}
Cesar Canassa
nice but not unfortunately cross-browser :(
galambalazs
it's cross-browser. but you will have to define the some and filter methods if the client is using IE
Cesar Canassa