
Question:
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?
Answer1: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.
<pre class="snippet-code-js lang-js prettyprint-override">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);
Answer2: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;
<pre class="snippet-code-js lang-js prettyprint-override">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));
Answer3:This is what I'd do:
<pre class="snippet-code-js lang-js prettyprint-override">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
.