1

I have an array that contains some single items and some arrays:

var groceries = ["toothpaste", ["plums", "peaches", "pineapples"], ["carrots", "corn", "green beans"], "orange juice", ["chocolate", "ice cream"], "paper towels", "fish"];

I want to write a function to remove some of these items or arrays when called.

For the single items, I wrote this function:

function removeItems(arr, item) {
  for ( var i = 0; i < item.length; i++ ) {
    var index = arr.indexOf(item[i]);
    if (index > -1) {
      arr.splice(index, 1);
    }
  }
};

So then I can call:

removeItems(groceries, ["fish", "orange juice"]);

And this works exactly as I want it to. However, I can't figure out how to make the function also be able to remove the arrays (e.g. ["chocolate", "ice cream"]) from within the larger array. How would I go about that?

2
  • if I just want to remove "chocolate", would I just remove chocolate or the array ["chocolate", "ice cream"] Commented Aug 27, 2017 at 7:50
  • I will never want to remove just part of the arrays within the array. Only remove the single items or the entire arrays. Does that make sense? So in your example, ["chocolate", "ice cream"]. Commented Aug 27, 2017 at 7:52

3 Answers 3

4

Use Array#reduce to create a dictionary of keys. If the item is an array, join all values to create the key. Afterwards filter all items by generating the same keys, and checking them against the dictionary.

Note - Array#filter creates a new array, and doesn't change the original array.

var groceries = ["toothpaste", ["plums", "peaches", "pineapples"], ["carrots", "corn", "green beans"], "orange juice", ["chocolate", "ice cream"], "paper towels", "fish"];

function removeItems(arr, toRemove) {
  function createKey(item) {
    return Array.isArray(item) ? item.join('-') : item;
  }

  var removeDict = toRemove.reduce(function(d, item) {
    var key = createKey(item);
    
    d[key] = true;
    
    return d;
  }, {});

  return arr.filter(function(item) {
    var key = createKey(item);
    
    return !removeDict[key];
  });
}

var result = removeItems(groceries, ["fish", "orange juice", ["chocolate", "ice cream"]]);

console.log(result);

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

3 Comments

This is perfect. Thank you for the explanation, really helpful.
Instead of createKey why don't you just use JSON.stringify? See my answer.
@AaditMShah - Thanks. I've considered that, but I'm not sure if stringify is not a bit of an overkill for this case.
0

In problems like deleting elements from the subject, i tend to stay away from using the functional array methods since they will iterate according to the initial item count even if you start deleting the items. So my solution would be rather imperative;

function remover(itemToDelete, items){
  var i       = 0,
      check   = false;
  
  for (var item of items){
    check = Array.isArray(item) ? item.includes(itemToDelete)
                                : item === itemToDelete;
    check ? items.splice(i,1)
          : i++;
  }
  return items;
}

var groceries = ["toothpaste", ["plums", "peaches", "pineapples"], ["carrots", "corn", "green beans"], "orange juice", ["chocolate", "ice cream"], "paper towels", "fish"];

console.log(remover("chocolate", groceries));
console.log(remover("fish", groceries));

Comments

0

This is what I'd do:

const groceries = [
    "toothpaste",
    ["plums", "peaches", "pineapples"],
    ["carrots", "corn", "green beans"],
    "orange juice",
    ["chocolate", "ice cream"],
    "paper towels",
    "fish"
];

const equals = (x, y) => JSON.stringify(x) === JSON.stringify(y);

const removeItems = (xs, ys) => xs.filter(x => !ys.some(y => equals(x, y)));

const result = removeItems(groceries, [
    "fish",
    "orange juice",
    ["chocolate", "ice cream"]
]);

console.log(result);

First, we define what it means for two values to be equal. Next, we define removeItems using this value equality. We say keep all those x which are not equal to any y.

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.