0

I have an array of elements which I want to maintain efficiently, adding and removing arrays of elements over time.

var myElements = $('.initial');

jquery's merge() seems perfect for adding items as it doesn't create a new array and just adds to the existing one:

$.merge(myElements, $('.to-add'));

Is there an equivalent for removing, that also modifies the array in-place? Something like:

$.exclude(myElements, $('.to-remove'));

I do actually have arrays of DOM elements, and the selectors are just used as examples.

jozxyqk
  • 16,424
  • 12
  • 91
  • 180
  • 1
    Can't you use `splice()`? https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/splice – adamj Jan 12 '16 at 03:51
  • @adamj it looks like splice can only remove a range of elements given by and index and length, whereas I want to remove elements from another array, which could exist anywhere and in any order. – jozxyqk Jan 12 '16 at 03:53
  • @jozxyqk Note, passing `jQuery()` as parameter to `$.exclude()` would create a new object – guest271314 Jan 12 '16 at 19:17

4 Answers4

2

Assuming that you're after the relative complement of b in a. And you don't want to create additional objects while process. The function is for both plain Array and jQuery set. (thus used $.each, $.inArray instead of Array.prototype.forEach Array.prototype.indexOf)

I wrote a function that fits your requirement.

$.exclude = function(a,b) {
    var idx;
    $.each(b, function(i, val) {
      while((idx = $.inArray(val, a)) !== -1) {
         a.splice(idx, 1);         
      }
    })
    return a;
}

test this code here https://jsfiddle.net/happyhj/uwd4L1dm/8/

and you can use like this.

$.exclude(myElements, $('.to-remove'));
Hee Jae Kim
  • 121
  • 1
  • 6
  • Looks more like O(n * m) to me. You could replace one of the loops with `indexOf`, but the main point of using `splice` to remove elements in-place seems to be the way to go. – jozxyqk Jan 12 '16 at 06:02
  • @jozxyqk jQuery set not have indexOf function. but that is good suggestion. I will use $.inArray(). – Hee Jae Kim Jan 12 '16 at 06:20
1

use jquery not method,

var filtered = $(myElements).not($('.to-remove'));

Azad
  • 5,144
  • 4
  • 28
  • 56
  • although not in-place, that's pretty close to what I'm after. didn't realise `not()` could take an array, rather than a selector or element. – jozxyqk Jan 12 '16 at 04:07
  • you can create own exclude function using `not()`. – Azad Jan 12 '16 at 04:12
  • my issue with in-place is for efficiency. every removal will leave an unused array for the garbage collector to deal with. as the array grows in size, this would start to slow things down. – jozxyqk Jan 12 '16 at 04:17
  • @charlietfl in my case I have an array, not a selector (was using that just for an example). azzi was correct to include it in this answer. – jozxyqk Jan 12 '16 at 04:38
0

You can use delete to remove an element from an array and then use $.grep to remove the empty space.

//[0] since $("#id") will be a jquery Object
//[0] will return the particular DOM element

var orgArray = [$("#merge1")[0],$("#merge2")[0],$("#merge3")[0]];
var secArray = [$("#merge4")[0],$("#merge5")[0]]

// Will merge other two values; 
// jQuery merge will merge contents of 
//two array into first array

var merArray = $.merge(secArray, orgArray);

// Want to remove $("#merge2");

var getIndex = merArray.indexOf($("#merge2")[0]);
    if(getIndex >-1){
     delete merArray[getIndex] 
    }

// length before filtering
$("#l1").text(merArray.length);

//Now will remove Empty Space

merArray = $.grep(merArray,function(n){
 return n==0 || n
});
$("#l2").text(merArray.length);

JSFIDDLE

brk
  • 48,835
  • 10
  • 56
  • 78
0

You are using methods that are meant for array literals. jQuery already has method add() which will return a modified jQuery object that includes the elements matching the selector

var myElements = $('.initial');
var newCollection = myElements.add('.to-add');    
newCollection.not('.to-remove').doSomething();

Don't think of jQuery objects as arrays although they are array like.

Reference add()

It's not clear what your overall objective really is but most likely you can manage it with any number of filtering methods that already exist within the api

charlietfl
  • 170,828
  • 13
  • 121
  • 150
  • `.not()` creates a new jQuery object – guest271314 Jan 12 '16 at 19:33
  • @guest271314 not sure what relevance is. It won't change `newCollection`, just pass that new object to next method in chain – charlietfl Jan 12 '16 at 19:36
  • _"the .not() method constructs a new jQuery object from a subset of the matching elements."_ https://api.jquery.com/not/ . Requirement appear to be not to create a new jQuery collection or array ?, only push to, or delete from `newCollection` ? Though at OP, not certain why, a new jQuery object is passed as parameter to `$.exclude()` ? and OP does not address this portion of `js` at Question directly ; could be incorrect, here, as to interpretation of requirement – guest271314 Jan 12 '16 at 19:39