Removing elements from an array by value in Javascript - javascript

It's a bit fuzzy for me, but I'm trying to create a simple function that takes an array and some arguments and removes the arguments from the array.
For example if I have an array such as [1,2,3,4] and the arguments 2,3 it would return [1,4] as a result.
This is what I have so far:
const removeFromArray = (arr) => {
let args = Array.from(arguments);
return arr.filter(function (item) {
!args.includes(item);
});
}
It doesn't work though. It works if I want to remove all the items from the array, but doesn't if I only go for specific ones.
How can I make this work so that it works even if I'm supplying an argument that is not part of the array (I want it to ignore those) and also if I have strings in the array as well?
Thanks in advance!

You could take rest parameters ... for the items to exclude the values.
const removeFromArray = (array, ...items) => array.filter(item => !items.includes(item));
console.log(removeFromArray([1, 2, 3, 4], 1, 4))
To use you style, you need to exclude the first item of arguments, because this is the array with all items.
let args = Array.from(arguments).slice(1);
// ^^^^^^^^^

In arrow functions the implicit object arguments doesn't exist, so declare the function using the keyword function, likewise, you need to return the result of the function includes within the handler of the function filter.
const removeFromArray = function() {
let [arr, ...args] = Array.from(arguments);
return arr.filter(function (item) {
return !args.includes(item);
});
}
console.log(removeFromArray([1,2,3,4], 2, 3));

Add a second parameter for the items you want to have removed.
const removeFromArray = (arr, toBeRemoved) => {
return arr.filter(item => !toBeRemoved.includes(item));
}
Example call:
const array = [1, 2, 3, 4]
const newArray = removeFromArray(arr, [2, 3])
console.log(newArray) // [1, 4]

Stick it to the Array.prototype, might use it somewhere else
Array.prototype.remove = function(...args) {
return this.filter(v => !args.includes(v));
}

Related

Remove multiple elements from an array using a function

What I am trying to do is to return the [1, 4] array, however, I do not understand what's the mistake which ends up returning [1]. Any clues? Thank you!
const removeFromArray = function(arr) {
for (let i = arr.length - 1; i >= 0; i--) {
arr.splice(arr[i], 2);
}
return arr;
};
console.log(
removeFromArray([1, 2, 3, 4], 3, 2)
)
It's not exactly clear to me what you want to achieve.
You define a function which only takes one argument:
const removeFromArray = function(arr) {...}
But then you call the function with 3 arguments, an array and two numbers:
removeFromArray([1, 2, 3, 4], 3, 2)
Now your function only takes the first input (the array) and removes all elements instead the first one.
Please consider the syntax: splice(start, deleteCount)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice
Maybe this rm() does what you want?
const rm=(arr, ...rem)=>arr.filter(a=>!rem.includes(a));
console.log(rm([1, 2, 3, 4], 3, 2));
It treats the first argument as the array arr that is to be filtered. The following arguments then make up the array rem, containing all the elements that are to be taken out of array arr.
You should consider using the built in filter method for arrays.
removeFromArray = (array, unwanted, otherUnwanted) => {
const filtered = array.filter((number) => {
return number !== unwanted && number !== otherUnwanted
});
return filtered;
};
console.log(removeFromArray[1,2,3,4], 3, 2]
To make the function more scalable for future use the second parameter could be an array.
betterRemoveFromArray = (array, unwantedNumbers) => {
const filtered = array.filter((number) => {
return !unwantedNumbers.includes(number)
});
return filtered;
};
console.log(removeFromArray3([1, 2, 3, 4], [2, 3]));
You need to write a variadic function which means it accepts a variable number of arguments. To represent it, use the rest parameter syntax which allows the function to accept an indefinite number of arguments as an array.
Then, use the filter method on the 1st argument, like so:
const removeFromArray = function(arr, ...theArgs) {
arr = arr.filter(arg => !theArgs.includes(arg));
return arr;
};
console.log(
removeFromArray([1, 2, 3, 4], 3, 2)
)

Iterating inside JavaScript filter method

I am trying to compare two given parameters of a function. The exact problem is as follows:
You will be provided with an initial array (the first argument in the destroyer function), followed by one or more arguments. Remove all elements from the initial array that are of the same value as these arguments.
Note
You have to use the arguments object.
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3)); // expected output: [1,1]
I am using filter method to iterate over the array but I couldn't compare the args with the elements of the array inside the callback of the filter.
function destroyer(arr, ...args) {
let result = arr.filter(num => {
for (let i = 0; i<=args.length; i++ ){
num !== args[i]
}
});
return result;
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3));
I can iterate with for loop but I cannot use the output of for loop to do filter iteration.
Any ideas?
Probably an easier way to achieve the goal using .filter() with .includes(). Additionally you can use ...rest so called rest parameters for you function, see form the documentation:
The rest parameter syntax allows us to represent an indefinite number of arguments as an array.
Try as the following:
const destroyer = (arr, ...rest) => {
return arr.filter(num => !rest.includes(num));
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3));
I hope this helps!
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
Example:
const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];
const result = words.filter(word => word.length > 6);
console.log(result);
// expected output: Array ["exuberant", "destruction", "present"]
via MDN
Filter iterates over all elements of some array and returns a new array. It puts an element in the new array only if callback (your function invoked as a parameter of filter) return true otherwise it's omitted.
Next it's worth to use rest parameters to achieve two arrays (initial and values to exclude).
The rest parameter syntax allows us to represent an indefinite number of arguments as an array.
function sum(...theArgs) {
return theArgs.reduce((previous, current) => {
return previous + current;
});
}
console.log(sum(1, 2, 3));
// expected output: 6
console.log(sum(1, 2, 3, 4));
// expected output: 10
Solution with explanation:
//Declare your function, first parameter is initial array, the second one is also array created by using rest parameters
function destroyer(initialArray = [], ...toExclude) {
// filter initialArray, if el (single element) is NOT included in "toExclude" it returns true
// and add this particular element to the result array
let result = initialArray.filter(el => toExclude.includes(el) == false);
//return result
return result;
}

Sorting array multiple times and storing in an object [duplicate]

Let's suppose I wanted a sort function that returns a sorted copy of the inputted array. I naively tried this
function sort(arr) {
return arr.sort();
}
and I tested it with this, which shows that my sort method is mutating the array.
var a = [2,3,7,5,3,7,1,3,4];
sort(a);
alert(a); //alerts "1,2,3,3,3,4,5,7,7"
I also tried this approach
function sort(arr) {
return Array.prototype.sort(arr);
}
but it doesn't work at all.
Is there a straightforward way around this, preferably a way that doesn't require hand-rolling my own sorting algorithm or copying every element of the array into a new one?
You need to copy the array before you sort it. One way with es6:
const sorted = [...arr].sort();
The spread-syntax as array literal (copied from mdn):
var arr = [1, 2, 3];
var arr2 = [...arr]; // like arr.slice()
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator
Just copy the array. There are many ways to do that:
function sort(arr) {
return arr.concat().sort();
}
// Or:
return Array.prototype.slice.call(arr).sort(); // For array-like objects
Try the following
function sortCopy(arr) {
return arr.slice(0).sort();
}
The slice(0) expression creates a copy of the array starting at element 0.
You can use slice with no arguments to copy an array:
var foo,
bar;
foo = [3,1,2];
bar = foo.slice().sort();
You can also do this
d = [20, 30, 10]
e = Array.from(d)
e.sort()
This way d will not get mutated.
function sorted(arr) {
temp = Array.from(arr)
return temp.sort()
}
//Use it like this
x = [20, 10, 100]
console.log(sorted(x))
Update - Array.prototype.toSorted() proposal
The Array.prototype.toSorted(compareFn) -> Array is a new method which was proposed to be added to the Array.prototype and is currently in stage 3 (Soon to be available).
This method will keep the target Array untouched and returns a copy of it with the change performed instead.
Anyone who wants to do a deep copy (e.g. if your array contains objects) can use:
let arrCopy = JSON.parse(JSON.stringify(arr))
Then you can sort arrCopy without changing arr.
arrCopy.sort((obj1, obj2) => obj1.id > obj2.id)
Please note: this can be slow for very large arrays.
Try this to sort the numbers. This does not mutate the original array.
function sort(arr) {
return arr.slice(0).sort((a,b) => a-b);
}
There's a new tc39 proposal, which adds a toSorted method to Array that returns a copy of the array and doesn't modify the original.
For example:
const sequence = [3, 2, 1];
sequence.toSorted(); // => [1, 2, 3]
sequence; // => [3, 2, 1]
As it's currently in stage 3, it will likely be implemented in browser engines soon, but in the meantime a polyfill is available here or in core-js.
I think that my answer is a bit too late but if someone come across this issue again the solution may be useful.
I can propose yet another approach with a native function which returns a sorted array.
This code still mutates the original object but instead of native behaviour this implementation returns a sorted array.
// Remember that it is not recommended to extend build-in prototypes
// or even worse override native functions.
// You can create a seperate function if you like
// You can specify any name instead of "sorted" (Python-like)
// Check for existence of the method in prototype
if (typeof Array.prototype.sorted == "undefined") {
// If it does not exist you provide your own method
Array.prototype.sorted = function () {
Array.prototype.sort.apply(this, arguments);
return this;
};
}
This way of solving the problem was ideal in my situation.
You can also extend the existing Array functionality. This allows chaining different array functions together.
Array.prototype.sorted = function (compareFn) {
const shallowCopy = this.slice();
shallowCopy.sort(compareFn);
return shallowCopy;
}
[1, 2, 3, 4, 5, 6]
.filter(x => x % 2 == 0)
.sorted((l, r) => r - l)
.map(x => x * 2)
// -> [12, 8, 4]
Same in typescript:
// extensions.ts
Array.prototype.sorted = function (compareFn?: ((a: any, b: any) => number) | undefined) {
const shallowCopy = this.slice();
shallowCopy.sort(compareFn);
return shallowCopy;
}
declare global {
interface Array<T> {
sorted(compareFn?: (a: T, b: T) => number): Array<T>;
}
}
export {}
// index.ts
import 'extensions.ts';
[1, 2, 3, 4, 5, 6]
.filter(x => x % 2 == 0)
.sorted((l, r) => r - l)
.map(x => x * 2)
// -> [12, 8, 4]

How do I replace an array element without modifying the original array and creating copy?

I'm trying to create a pure function that receives an array as parameter and now I want to replace an element at a given index without modifying the provided array argument.
Basically I'm looking for something like this:
export const muFunc = (arr) => {
return arr.replaceElementAt(1, 'myNewValue'); // This doesnt modify arr at all
}
How can I do that?
Simply copy the array. A simple way to do that is slice:
export const muFunc = (arr) => {
var newArray = arr.slice();
newArray[1] = 'myNewValue';
return newArray;
};
From a comment on the question:
As the topic says - I'm trying to find out if it's possible without creating a copy of the array
No it's not possible — well, not reasonably. You have to either modify the original, or make a copy.
You could create proxy object that just returns a different value for the "1" property, but that seems unnecessarily complicated.
You could take advantage of Object.assign and do something like:
const arr = [1, 2, 3, 4, 5];
const updatedArr = Object.assign([], arr, {1: 'myNewValue'});
console.log(arr); // [1, 2, 3, 4, 5]
console.log(updatedArr); // [1, "myNewValue", 3, 4, 5]
You can use map function to achieve this
var arr = [1,2,3,4,5,6,7,89];
arr.map(function (rm) {
if (rm == 2) {
return 3
} else {
return rm
}
})
Try this :
function replace(l) {
return l.splice("new value",1);
};
var x = replace(arr);

How can you sort an array without mutating the original array?

Let's suppose I wanted a sort function that returns a sorted copy of the inputted array. I naively tried this
function sort(arr) {
return arr.sort();
}
and I tested it with this, which shows that my sort method is mutating the array.
var a = [2,3,7,5,3,7,1,3,4];
sort(a);
alert(a); //alerts "1,2,3,3,3,4,5,7,7"
I also tried this approach
function sort(arr) {
return Array.prototype.sort(arr);
}
but it doesn't work at all.
Is there a straightforward way around this, preferably a way that doesn't require hand-rolling my own sorting algorithm or copying every element of the array into a new one?
You need to copy the array before you sort it. One way with es6:
const sorted = [...arr].sort();
The spread-syntax as array literal (copied from mdn):
var arr = [1, 2, 3];
var arr2 = [...arr]; // like arr.slice()
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator
Just copy the array. There are many ways to do that:
function sort(arr) {
return arr.concat().sort();
}
// Or:
return Array.prototype.slice.call(arr).sort(); // For array-like objects
Try the following
function sortCopy(arr) {
return arr.slice(0).sort();
}
The slice(0) expression creates a copy of the array starting at element 0.
You can use slice with no arguments to copy an array:
var foo,
bar;
foo = [3,1,2];
bar = foo.slice().sort();
You can also do this
d = [20, 30, 10]
e = Array.from(d)
e.sort()
This way d will not get mutated.
function sorted(arr) {
temp = Array.from(arr)
return temp.sort()
}
//Use it like this
x = [20, 10, 100]
console.log(sorted(x))
Update - Array.prototype.toSorted() proposal
The Array.prototype.toSorted(compareFn) -> Array is a new method which was proposed to be added to the Array.prototype and is currently in stage 3 (Soon to be available).
This method will keep the target Array untouched and returns a copy of it with the change performed instead.
Anyone who wants to do a deep copy (e.g. if your array contains objects) can use:
let arrCopy = JSON.parse(JSON.stringify(arr))
Then you can sort arrCopy without changing arr.
arrCopy.sort((obj1, obj2) => obj1.id > obj2.id)
Please note: this can be slow for very large arrays.
Try this to sort the numbers. This does not mutate the original array.
function sort(arr) {
return arr.slice(0).sort((a,b) => a-b);
}
There's a new tc39 proposal, which adds a toSorted method to Array that returns a copy of the array and doesn't modify the original.
For example:
const sequence = [3, 2, 1];
sequence.toSorted(); // => [1, 2, 3]
sequence; // => [3, 2, 1]
As it's currently in stage 3, it will likely be implemented in browser engines soon, but in the meantime a polyfill is available here or in core-js.
I think that my answer is a bit too late but if someone come across this issue again the solution may be useful.
I can propose yet another approach with a native function which returns a sorted array.
This code still mutates the original object but instead of native behaviour this implementation returns a sorted array.
// Remember that it is not recommended to extend build-in prototypes
// or even worse override native functions.
// You can create a seperate function if you like
// You can specify any name instead of "sorted" (Python-like)
// Check for existence of the method in prototype
if (typeof Array.prototype.sorted == "undefined") {
// If it does not exist you provide your own method
Array.prototype.sorted = function () {
Array.prototype.sort.apply(this, arguments);
return this;
};
}
This way of solving the problem was ideal in my situation.
You can also extend the existing Array functionality. This allows chaining different array functions together.
Array.prototype.sorted = function (compareFn) {
const shallowCopy = this.slice();
shallowCopy.sort(compareFn);
return shallowCopy;
}
[1, 2, 3, 4, 5, 6]
.filter(x => x % 2 == 0)
.sorted((l, r) => r - l)
.map(x => x * 2)
// -> [12, 8, 4]
Same in typescript:
// extensions.ts
Array.prototype.sorted = function (compareFn?: ((a: any, b: any) => number) | undefined) {
const shallowCopy = this.slice();
shallowCopy.sort(compareFn);
return shallowCopy;
}
declare global {
interface Array<T> {
sorted(compareFn?: (a: T, b: T) => number): Array<T>;
}
}
export {}
// index.ts
import 'extensions.ts';
[1, 2, 3, 4, 5, 6]
.filter(x => x % 2 == 0)
.sorted((l, r) => r - l)
.map(x => x * 2)
// -> [12, 8, 4]

Categories

Resources