Removing repeated values from array with multiple arguments - javascript

These are the full instructions for what I am trying to accomplish :
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.
This is the solution I have:
function destroyer(arr) {
var args = Array.prototype.slice.call(arguments);
args.slice(0,1);
return arr.filter(function(elements) {
return args.indexOf(element) === -1;
});
}
Keep in mind that there could be any number of arguments (not just 2 or 3).
The solution I have isn't working. What is wrong with my current solution and how can I fix it with an explanation?

Your solution is almost working.
The problems:
args.slice(0,1); does not modify the array (anyway this method just returns an array with the first element). Use args.shift() instead to remove the first element
function(elements) should be function(element) in the filter callback.
A working solution:
function destroyer(arr) {
var args = Array.prototype.slice.call(arguments);
args.shift();
return arr.filter(function(element) {
return args.indexOf(element) === -1;
});
}
console.log(destroyer([1, 2, 3, 5, 5], 1, 5)); // prints [2, 3]
Check the working demo.

Related

How can i target elements in another array via .filter()

Im trying to return the values in argument[0] that are not equal to the values of arguments[1] and so on.
Ive created a variable 'let argArr' that holds the values of the arguments after the first, Im trying to understand why in my .filter() i cannot target 'let argArr'?
function destroyer(arr) {
let argArr = [];
for (let i = 1; i < arguments.length; i++) {
argArr.push(arguments[i])
}
return arr.filter(i => i !== argArr)
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3));
You are comparing an arr array's element to the argArr what is wrong.
The right way is to check if element is inside argArr and filter if yes.
return arr.filter(i => !argArr.includes(i))
Instead of using arguments explicitly specify the array as the first argument, and then use rest parameters to gather all the remaining arguments into an array. Then use filter to return only those elements in the array that are not in the rest array.
function destroyer(arr, ...rest) {
return arr.filter(el => !rest.includes(el));
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3));
Use spread operator to treat arguments as normal array
function foo() {
return [...arguments].filter(el => el);
}
console.log(foo(1,2,3))

specifying the value change of a Variable value over time not working

function destroyer(arr) {
var arg = Array.prototype.slice.call(arguments);
arg.splice(0, 1);
return arr.filter(function (val){
return arg.indexOf(val) === -1;
});
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
this code is working accurately. But if replace arg.splice(0, 1) with arg = arg.splice(0, 1); , the code doesn't work. Since arg is a variable so its value can be changed over the course of entire code, why it doesn't work like this? Pardon me if this ques looks silly, but i am new to javascript and very curious in exploring every bit of knowledge about it.
Your code not using arg = is correct (though you can do it more efficiently, more below). arg.splice(0, 1) removes the first element from the original array (changing the array in place), and returns a new array containing only the element that was removed. That is:
var a = [1, 2, 3];
console.log(a.splice(0, 1)); // [1]
console.log(a); // [2, 3]
If you use arg = arg.splice(0, 1); you're saying "Remove the first element from arg and replace the arg variable's value with a reference to the new array containing only that removed element. So your subsequent use of arg uses the array containing the removed entry, instead of the array you wanted to use.
You can and probably should avoid splice entirely. Instead, just skip the first argument when copying arguments:
function destroyer(arr) {
var arg = Array.prototype.slice.call(arguments, 1);
// Note --------------------------------------^^^
return arr.filter(function(val) {
return arg.indexOf(val) === -1;
});
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);

Javascript: please help me understand this function

I've been trying to understand this function for quite a while, but it just doesn't make sense to me. The goal of the function is to remove any numbers within the array of arguments that match the other argument numbers.
Why is it necessary to slice the array for the function to work?
Is args.splice(0,1) redundant? I removed it and nothing changed.
It seems like the filter function does the bulk of the work, but I don't see how it actually filters for the numbers...
function destroyer(arr) {
var args = Array.prototype.slice.call(arguments);
args.splice(0, 1);
return arr.filter(function(element) {
return args.indexOf(element) === -1;
});
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
Let's go through it line by line:
var args = Array.prototype.slice.call(arguments);
JavaScript's arguments variable is similar to an array but it's not an array. You can try this yourself: arguments instanceof Array will give false. So applying the slice method from the Array prototype will simply convert arguments to a real array.
args.splice(0, 1);
This is to remove the first argument, which is arr in your case.
return arr.filter(function(element) {
return args.indexOf(element) === -1;
});
This will go through all the numbers in arr and will check each one of them if it exists in the arguments. When indexOf() returns -1 it means the element was not found in the array.
Slice does not alter. It returns a shallow copy of elements from the original array. Elements of the original array are copied into the returned array.
Take this example
var object = {
'0': 'zero',
'1': 'one',
'2': 'two',
'3': 'three',
'4': 'four',
length: 5
};
var sliced = Array.prototype.slice.call( object, 3 );
['three','four']; //output
passe Arguments [Array[6], 2, 3]
Arguments after splicing or remove first element of argument [2, 3]
so closure function filters element which is present in first element of array with other two element. returning just [1, 1]
To understand what's going on, we need to understand the Function.prototype.call method.
It invokes the Array.prototype.slice method on the first argument you pass to it, which in this case is the magical JS arguments object, and then passes in whatever arguments follow.
Thus Array.prototype.splice is unnecessary, and you can just write:
function destroyer(arr) {
var rest = Array.prototype.slice.call(arguments, 1);
return arr.filter(function(element) {
return rest.indexOf(element) === -1;
});
}
in fact, this has been implemented in ES2015+ with the spread operator, so you could write:
function destroyer(arr, ...rest) {
return arr.filter(function(element) {
return rest.indexOf(element) === -1;
});
}
I've added comments, please see if it helps you to understand the function.
function destroyer(arr) {
// arr just holds [1, 2, 3, 1, 2, 3]
var args = Array.prototype.slice.call(arguments);
// args contains nested array with all input params [[1, 2, 3, 1, 2, 3], 2, 3]
args.splice(0, 1);
//args is spliced and we have [2,3] in args
//Filter arr=[1, 2, 3, 1, 2, 3] elements, condition it must not be in args i.e [2,3]
return arr.filter(function(element) {
return args.indexOf(element) === -1;
});
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
Please refer to the below documentation to read about arguments object used in this function:
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/arguments
In arr we will have [1,2,3,1,2,3] and
in args we will have [[1,2,3,1,2,3],2,3]
The filter function loop over arr
and args.indexOf(element) will return -1 if element is not in args.
So, for the first time in loop the element value is 1 and inside loop
args.indexOf(1) returns -1 because 1 is not present in args because at 0 index we have array and at 1st index we have 2 and at 2nd index we have 3. So the condition === -1 is true and returns 1 to the array that is going to be printed to the console.
for next element, i.e., 2 in arr, the statement args.indexOf(2) returns the first index at which 2 is present i.e., 1 in args array. for likewise entire loop will be executed for arr

Javascript: Why array variable assignment is behaving differently inside and outside this function?

For the life of me, I just can't figure out what I'm doing wrong here.
I'm trying to use both the reduce and concat array methods to take all of the values of a 2d array and combine them into a single value (basically condense them into a single array and then sum them up).
The problem that I keep running into is that when I try to make a for/loop to concat each array element, the argument that I'm passing into the function is not being recognized as an array, thus my call to .concat() is failing. I've placed a console.log() at the beginning of the function to see if the element is being recognized as the first array element in the 2d array, and it's coming up as "1"(?).
I tried another test outside of the function, and it logs as the actual array element. What am I doing wrong here? code below:
var arrays = [[1, 2, 3], [4, 5], [6]];
var myArray = arrays[0]; // Test
console.log(myArray); // Test
var flatArray = arrays.reduce(function(arrays)
{
console.log(arrays[0]); // Test
for (var i = 0; i < arrays.length - 1; i++)
{
arrays[0].concat(arrays[i+1]);
}
return arrays;
});
console.log(flatArray);
This is the output that I keep getting:
Array [ 1, 2, 3 ]
1
TypeError: arrays[0].concat is not a function
It's almost seems like array is being converted to a number-type when inside the function...?
You have an error in your code here:
var flatArray = arrays.reduce(function(param) {})
that param will be an element of your arrays vector.
Check this https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
You are using .reduce() incorrectly and you don't even need to use it to flatten an array. You can just do this:
var flatArray = [].concat.apply([],arrays);
Working demo: http://jsfiddle.net/jfriend00/wfjyfp42/
To understand .reduce(), the callback you pass it gets four arguments (see MDN reference). The first two arguments are important in using .reduce() correctly:
callback(previousValue, currentValue, index, array)
The previousValue is the accumulated value so far in the reduction. The currentValue is the next element of the array that is being iterated. The last two arguments do not need to be used if not needed.
Your code is only using the previousValue so it is never looking at the next item in the array as passed in by .reduce().
You could make a solution work using .reduce() like this:
var flatArray = arrays.reduce(function(previousValue, currentValue) {
return previousValue.concat(currentValue);
}, []);
Working demo: http://jsfiddle.net/jfriend00/2doohfc5/
Reduce performs an operation on two elements.
var sum = [[1, 2, 3], [4, 5], [6]].reduce(function(a, b) {
return a.concat(b);
}).reduce(function(a, b) {
return a + b;
});

How to get a slice from "arguments"

All you know that arguments is a special object that holds all the arguments passed to the function.
And as long as it is not an array - you cannot use something like arguments.slice(1).
So the question - how to slice everything but first element from arguments?
UPD:
seems like there is no way without converting it to an array with
var args = Array.prototype.slice.call(arguments);
If someone posts another solution it would be great, if not - I'll check the first one with the line above as an answer.
Q. How to slice everything but first element from arguments?
The following will return an array containing all arguments except the first:
var slicedArgs = Array.prototype.slice.call(arguments, 1);
You don't have to convert arguments to an array first, do it all in one step.
Meddling with array functions is not actually necessary.
Using rest parameter syntax ...rest is cleaner and more convenient.
Example
function argumentTest(first, ...rest) {
console.log("First arg:" + first);
// loop through the rest of the parameters
for (let arg of rest) {
console.log("- " + arg);
}
}
// call your function with any number of arguments
argumentTest("first arg", "#2", "more arguments", "this is not an argument but a contradiction");
...Rest
See the example Fiddle
See MDN Documentation page
From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments:
You should not slice on arguments because it prevents optimizations in
JavaScript engines (V8 for example). Instead, try constructing a new
array by iterating through the arguments object.
So Paul Rosiana's answer above is correct
This can be a way:
var args = Array.from(arguments).slice(1);
You can "slice without slicing" by procedurally walking the arguments object:
function fun() {
var args = [];
for (var i = 1; i < arguments.length; i++) {
args.push(arguments[i]);
}
return args;
}
fun(1, 2, 3, 4, 5); //=> [2, 3, 4, 5]
You can use the method [].slice.call(arguments, 1)
[].slice will return you the slice function object and you can call it as the arguments and 1 are the parameters
You can use ...rest within the function to separate the first and the rest of the arguments:
function foo(arr) {
const [first, ...rest] = arguments;
console.log(`first = ${first}`);
console.log(`rest = ${rest}`);
}
//Then calling the function with 3 arguments:
foo(1,2,3)
you can use this too
function arg(myArr) {
let arg = Object.values(arguments).slice(2, 4);
console.log(arg);
return arg;
};
arg([1, 2, 3], 4, [5,6], 7)
see here for reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values
...
Arguments type is iterable, so using the ES6 (ES2015) spread ... operator, then use Array.slice([start], [end]) method, such as
function omitFirstAndLastArgument(value) {
const args = arguments.length > 2 ? [...arguments].slice(1, -1) : [];
return args;
}
omitFirstAndLastArgument(1, 2, 3, 4, 5, 6); // [2, 3, 4, 5]

Categories