I have a function which takes an array and further arguments like this:
function arrayandmore([1, 2, 3], 2, 3)
I need to return the array ([1, 2, 3]) without those elements which equals the arguments coming behind the array. So in this case, the returned array would be:
([1]).
One of my approaches is:
function destroyer(arr) {
var args = Array.from(arguments);
var i = 0;
while (i < args.length) {
var result = args[0].filter(word => word !== args[i]);
i++;
}
console.log(result);
}
destroyer([1, 1, 3, 4], 1, 3);
Console returns:
[ 1, 1, 4 ]
I don't understand, why it returns one too - I don't understand, why it does not work.
It is the same with using splice.
function destroyer(arr) {
var args = Array.from(arguments);
var quant = args.length - 1;
for (var i = 1; i <= quant; i++) {
if (arr.indexOf(args[i]) !== -1) {
arr = arr.splice(arr.indexOf(args[i]));
}
console.log(arr);
}
}
destroyer([1, 1, 3, 4], 1, 3);
I think, both ways should work. But I don't figure out why they don't.
Your while won't work because result is being overwritten in every loop. So, it only ever removes the last parameter to the destroyer function
You can use the rest parameter syntax to separate the array and the items to be removed.
Then use filter and includes like this:
function destroyer(arr, ...toRemove) {
return arr.filter(a => !toRemove.includes(a))
}
console.log(destroyer([1, 1, 3, 4, 5], 1, 3))
Related
destroyer(array1, some arguments) function should return the array1 excluding the arguments. I found some working ways like return arr = arr.filter(val => !rem.includes(val)); but I need to fix this code and find out why this code giving an incorrect result. It supposed to be [1]
function destroyer(arr, ...rem) {
for(let i = 0; i < arr.length; i++) {
if (rem.includes(arr[i])) {
arr.splice(i, 1);
};
};
return arr;
}
console.log(destroyer([3, 5, 1, 2, 2], 2, 3, 5));
function destroyer(arr, ...rem) {
const itemsToRemove = new Set(rem);
return arr.reduce((acc, curr) => itemsToRemove.has(curr) ? acc : [...acc, curr] ,[])
}
console.log(destroyer([3, 5, 1, 2, 2], 2, 3, 5));
The problem is the call of the function Array.prototype.splice within the for loop, this function is mutating the array and basically affects the indexes of the array, therefore the current index i is no longer valid.
To work around this, you can loop in a backward direction, this way we can mutate the array, and the current index is not affected.
One more thing, your approach is mutating the array, a better approach would be by using the function Array.prototype.filter along with the function Array.prototype.includes, see other answers.
function destroyer(arr, ...rem) {
for(let i = arr.length; i >= 0; i--) {
if (rem.includes(arr[i])) {
arr.splice(i, 1);
};
};
return arr;
}
console.log(destroyer([3, 5, 1, 2, 2], 2, 3, 5));
Or you can do it like this:
const destroyer=(arr, ...rem)=>arr.filter(v=>!rem.includes(v));
console.log(destroyer([3, 5, 1, 2, 2], 2, 3, 5));
I would like to compare multiple array and finally have an array that contain all unique values from different array. I tried to:
1,Use the filter method to compare the difference between 2 arrays
2,Call a for loop to input the arrays into the filter method
and the code is as follows
function diffArray(arr1, arr2) {
function filterfunction (arr1, arr2) {
return arr1.filter(function(item) {
return arr2.indexOf(item) === -1;
});
}
return filterfunction (arr1,arr2).concat(filterfunction(arr2,arr1));
}
function extractArray() {
var args = Array.prototype.slice.call(arguments);
for (var i =0; i < args.length; i++) {
diffArray(args[i],args[i+1]);
}
}
extractArray([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3]);
However it does not work and return the error message "Cannot read property 'indexOf' of underfined" .... What's wrong with the logic and what should I change to make it works?
Many thanks for your help in advance!
Re: For all that mark this issue as duplicated ... what I am looking for, is a solution that can let me to put as many arrays as I want for input and reduce all the difference (e.g input 10000 arrays and return 1 array for unique value), but not only comparing 2 arrays .. The solutions that I have seen are always with 2 arrays only.
I don't use filters or anything of the sort but it will get the job done. I first create an empty array and concat the next array to it. Then I pass it to delete the duplicates and return the newly "filtered" array back for use.
function deleteDuplicates(a){
for(var i = a.length - 1; i >= 0; i--){
if(a.indexOf(a[i]) !== i){
a.splice(i, 1);
}
}
return a;
}
function extractArray() {
var args = Array.prototype.slice.call(arguments), arr = [];
for (var i = 0; i < args.length; i++) {
arr = deleteDuplicates(arr.concat(args[i]));
}
return arr;
}
var arr = extractArray([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3]);
console.log(arr) //[3, 2, 5, 1, 7, 4, 6]
I am trying to use the filter method on an array to loop through the array based on a variable number of arguments.
Below is my attempt at this:
function destroyer(arr) {
var argArr = arr.slice.call(arguments, 1);
var filteredArray = arr.filter(function(val) {
for (var i = 0; i < argArr.length; i++) {
return val != argArr[i];
};
});
console.log(filteredArray);
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
When I do this, only the first element of the arguments array is disposed of. This therefore returns:
[1, 3, 1, 3]
I have found a few examples online of possible ways to resolve this but they are vastly different from what I understand just yet. Is there any way to get mine to work, or even understand why the additional elements of the arguments array are not being called.
If you use ES6 you can do it with rest operator and Array#includes function
function destroyer(arr, ...params){
return arr.filter(item => !params.includes(item));
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3));
With your logic you can do like this. If val is equal to the current argArr's item then return false, if nothing was found after the loop: return true
function destroyer(arr) {
var argArr = Array.prototype.slice.call(arguments, 1);
var filteredArray = arr.filter(function(val) {
for (var i = 0; i < argArr.length; i++) {
if(val === argArr[i]){
return false;
}
};
return true;
});
console.log(filteredArray);
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
Because with your code you always test if current element in filter is equal or not equal to second parameter in function which is 2 and return true/false. Instead you can use indexOf to test if current element in filter is inside arguments array.
function destroyer(arr) {
var argArr = arr.slice.call(arguments, 1);
var filteredArray = arr.filter(function(val) {
return argArr.indexOf(val) == -1
});
console.log(filteredArray);
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
Problem is in your this line
return val != argArr[i];
Change logic like this , it will avoid to do extra looping also .
function destroyer(arr) {
var argArr = arr.slice.call(arguments, 1); debugger
var filteredArray = arr.filter(function(val) {
return !(argArr.indexOf(val) >= 0);
});
console.log(filteredArray);
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
I'm working on a problem, where I am provided with an initial array (the first argument in the destroyer function), followed by one or more arguments. I need to remove all elements from the initial array that are of the same value as these arguments.
The function only takes 1 argument (the array), and there can be any number of additional arguments, which I can select as "arguments[index]".
Here is my code up to now:
function destroyer(arr) {
newArr= [ ];
newArr = arr.filter(function(x){
return x !== arguments[2]; //argumets[2] is equal to 3
});
return newArr;
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
// => returns [1, 2, 3, 1, 2, 3];
BUT if i enter 3, instead of arguments[2], the function returns [1,2,1,2].
What is going on?
Additionally, how can I loop through the code to test all other arguments, if I can't have a function in a loop?
arguments refers to the arguments of the second function
you can do something like this
function destroyer(arr) {
newArr= [ ];
var args = arguments;
newArr = arr.filter(function(x){
return x !== args[2];
});
return newArr;
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
First, make a reference to the top destroyer argument. Then use that inside your filter function.
function destroyer(arr) {
newArr= [ ]; var args = arguments;
newArr = arr.filter(function(x){
return x !== args[2]; //destoryer's arguments[2] is equal to 3
});
return newArr;
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
I'm calling a function inside of my script main
function func(a) {
var idx;
a=a.sort();
for (idx = 0; idx < a.length + 1; idx += 1) {
if (a.indexOf(idx) === -1) {
return idx;
}
}
return 0;
}
var array = [2,1,0];
var b = func(array);
console.log(array);
The function argument (a) is an array that is being passed to the func function.
When I try to access the array in the main body of the program after calling this function it's sorted.
Does node.js link the scope between the array passed to the 'func' function and the array that was passed to it?
After calling this code, array is sorted. Why is that?
This is even true if I declare a new variable, b inside the function scope.
function func(a) {
var idx, b;
b = a;
b = b.sort();
for (idx = 0; idx < a.length + 1; idx += 1) {
if (a.indexOf(idx) === -1) {
return idx;
}
}
return 0;
}
var array = [2,1,0];
var b = func(array);
console.log(array);
The above code has the same issue.
It's not a scope leak but a twofold reason for what is happening:
because sort directly modifies the array it is applied on (while also returning it)
functions in JavaScript work with pass by reference for objects
For reason #1 look at this simple example:
var a = [3,4,1,2];
a; // [3, 4, 1, 2]
a.sort(); // [1, 2, 3, 4]
a; // [1, 2, 3, 4]
As you can see it returns the sorted array which is nothing more than the array itself that has been modified by the sort.
For reason #2 look at this simple example:
function foo(a) { a.push('hello'); }
var arr = [1,2,3,4];
arr; // [1, 2, 3, 4]
foo(arr); // undefined
arr; // [1, 2, 3, 4, "hello"]
So combining those two reasons you can see that you are passing a reference to the array into the function and then directly modifying it with a sort.
If you want to do the same thing without modifying the original array you could use Array.prototype.slice() which returns a shallow copy of the original array.
var a = [3,4,1,2];
var arr = a.slice();
a; // [3, 4, 1, 2]
arr; // [3, 4, 1, 2]
arr.sort(); // [1, 2, 3, 4]
arr; // [1, 2, 3, 4]
a; // [3, 4, 1, 2]