Yossarian
Yossarian

Reputation: 99

How to remove one subset from an array in JS?

Let's say I have an array such as: [1, 1, 2, 2, 3, 3, 4, 5]
And I want to remove this array of elements [1, 2, 3, 4, 5]
So in the end I want to be left with [1, 2, 3]

I have tried using the method below but it removes all copies of the elements from the main array.

myArray = myArray.filter( function( el ) {
  return !toRemove.includes( el );
} );

Upvotes: 1

Views: 1492

Answers (4)

jo_va
jo_va

Reputation: 13964

Here is a way to do it using filter, indexOf and splice.

const input = [1, 1, 2, 2, 3, 3, 4, 5];

function removeSubset(arr, subset) {
  const exclude = [...subset];
  return arr.filter(x => {
    const idx = exclude.indexOf(x);
    if (idx >= 0) {
      exclude.splice(idx, 1);
      return false;
    }
    return true;
  });
}

console.log(removeSubset(input, [1, 2, 3, 4, 5]));

Upvotes: 2

Code Maniac
Code Maniac

Reputation: 37755

You can use Filter and Shitf and Sort

let arr = [1, 1, 2, 2, 3, 3, 4, 5]
let remove  = [1, 3, 2, 4, 5].sort((a,b)=>a-b)

let op = arr.sort((a,b)=>a-b).filter(e => ( remove.includes(e) ? (remove.shift(), false) : true ))


console.log(op)

Upvotes: 1

Shidersz
Shidersz

Reputation: 17190

One solution is looping on the array of elements to remove and for each one remove the first element found on the input array:

const input = [1, 1, 2, 2, 3, 3, 4, 5];

const removeItems = (input, items) =>
{
    // Make a copy, to not mutate the input.
    let clonedInput = input.slice();

    // Search and remove items.
    items.forEach(x =>
    {
        let i = clonedInput.findIndex(y => y === x);
        if (i >= 0) clonedInput.splice(i, 1);
    });
    
    return clonedInput;
}

console.log(removeItems(input, [1,2,3,4,5]));
console.log(removeItems(input, [1,2]));
console.log(removeItems(input, [1,99,44,5]));

If you still want to use filter, you can use the items to remove as the this argument of the filter, something like this:

const input = [1, 1, 2, 2, 3, 3, 4, 5];

const removeItems = (input, items) =>
{        
    return input.filter(function(x)
    {
        let i = this.findIndex(y => y === x);
        return i >= 0 ? (this.splice(i, 1), false) : true;
    }, items.slice());
}

console.log(removeItems(input, [1,2,3,4,5]));
console.log(removeItems(input, [1,2]));
console.log(removeItems(input, [1,99,44,5]));

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386520

You could get a Map and count the values and filter by checking the count and decrement the count if found.

var array = [1, 1, 2, 2, 3, 3, 4, 5],
    remove = [1, 2, 3, 4, 5],
    map = remove.reduce((m, v) => m.set(v, (m.get(v) || 0) + 1), new Map),
    result = array.filter(v => !map.get(v) || !map.set(v, map.get(v) - 1));

console.log(result);

Upvotes: 1

Related Questions