How to navigate and pull from an object in JavaScript - javascript

I am being given the function call destroyer([1, 2, 3, 1, 2, 3], 2, 3);. I want to be able to pull from the last 2, 3 part after the initial object, but I do not know how to go about this.
return arr[6]; and return arr[1][0] both return nothing. I am expecting to see 2 or 2, 3 (Last two numbers)
I tried researching Property Accessors, but I think I was looking in the wrong place for my answer.
Here's my full code:
function destroyer(arr) {
return arr;
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
Instead of getting the first array [1,2,3,1,2,3]
I want to get the parts after the array:
[1,2,3,1,2,3],2,3

You're destroyer function is only taking one argument, but you're passing it 3.
You have two options:
Use arguments to get an array-like of all the passed arguments, you'll then need to combine that with a method like slice to get only the second and third arguments. Additionaly since arguments isn't technically an array, you need to convert it to one before you can call a method like slice. My example uses Array.from however that is only available on newer browsers.
function destroyer(arr) {
return Array.from(arguments).slice(1,3);
}
console.log('Result: ', destroyer([1, 2, 3, 1, 2, 3],2,3));
Add additional parameters to your function definition. This is probably easier if you know you'll have exactly 3 arguments. And there are far fewer gotchas compared to using the magic arguments variable.
function destroyer(a, b, c) {
return [b, c];
}
console.log('Result: ', destroyer([1, 2, 3, 1, 2, 3], 2, 3));

try use arguments
example
function destroyer(){var arr = []; arr.push(arguments[1]);arr.push(arguments[2]); return arr};

Related

Understanding the 'necessity' of arguments of a forEach method

Documentation seems to suggest that in a forEach method, a callback function is a mandatory parameter and currentValue is a mandatory parameter of the callback function:
However this code - without a parameter of the callback function - works fine:
a = [1, 2, 3, 4, 5];
a.forEach(function () {
console.log(5);
})
How am I to understand when MDN positions 'optional' around some parameters and not around others?
There is no way to enforce that a function accepts mandatory parameters. However, without using the currentValue parameter, there is really no point of forEach; you do not necessarily need to use any of the other parameters, though. All of the arguments are still passed to the function, which you can see if you print out the arguments.
a = [1, 2, 3, 4, 5];
a.forEach(function () {
console.log("Number of arguments:", arguments.length);
console.log("Current value:", arguments[0]);
console.log("Index:", arguments[1]);
console.log("Original array:", arguments[2]);
})
In this case you don't use any elements of array, you just print 5. For main task any interaction of array you need the currentValue for do some manipulations with array
a = [1, 2, 3, 4, 5];
a.forEach(function (currentValue) {
console.log(currentValue, 5);
})

Ramda: Confused about pipe

I'm learning functional programming in JS and I'm doing it with Ramda.
I'm trying to make a function that takes parameters and returns a list. Here is the code:
const list = R.unapply(R.identity);
list(1, 2, 3); // => [1, 2, 3]
Now I tried doing this using pipe:
const otherList = R.pipe(R.identity, R.unapply);
otherList(1,2,3);
// => function(){return t(Array.prototype.slice.call(arguments,0))}
Which returns a weird function.
This:
const otherList = R.pipe(R.identity, R.unapply);
otherList(R.identity)(1,2,3); // => [1, 2, 3]
works for some reason.
I know this might be a newbie question, but how would you construct f(g(x)) with pipe, if f is unapply and g is identity?
Read the R.unapply docs. It's a function that gets a function and returns a function, which can take multiple parameters, collect it to a single array, and pass it as the parameter for the wrapped function.
So in the 1st case, it converts R.identity to a function that can receive multiple parameters and return an array.
In the 2nd case, R.unapply gets the result of R.identity - a single value, and not a function. If you pass R.identity as a parameter to the pipe, R.unapply gets a function and return a function, which is similar to the 1st case.
To make R.unapply work with R.pipe, you need to pass R.pipe to R.unapply:
const fn = R.unapply(R.pipe(
R.identity
))
const result = fn(1, 2, 3)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
It looks as though you really are thinking of pipe incorrectly.
When you use unapply(identity), you are passing the function identity to unapply.
But when you try pipe(identity, unapply), you get back a function that passes the results of calling identity to unapply.
That this works is mostly a coincidence: pipe(identity, unapply)(identity). Think of it as (...args) => unapply(identity(identity))(...args). Since identity(identity) is just identity, this turns into (...args) => unapply(identity)(...args), which can be simplified to unapply(identity). This only means something important because of the nature of identity.
You would use unapply to transform a function that would normally take its arguments as an array into a function that can take any number of positional arguments:
sum([1, 2, 3]); //=> 6
unapply(sum)(1, 2, 3) //=> 6
This allows you to, among many other things, map over any number of positional arguments:
unapply(map(inc))(1, 2) //=> [2, 3]
unapply(map(inc))(1, 2, 3) //=> [2, 3, 4]
unapply(map(inc))(1, 2, 3, 4) //=> [2, 3, 4, 5]
identity will always return its first argument. So unapply(identity)(1,2) is the same as identity([1,2]).
If your end goal was to create a function that returns a list of its arguments, I don't think you needed pipe in the first place. unapply(identity) was already doing that.
However, if what you need to do is to make sure that your pipe gets its parameters as a list, then you simply need to wrap pipe with unapply:
const sumplusplus = unapply(pipe(sum, inc, inc));
sumplusplus(1, 2, 3); //=> 8

How does this algorithm work? What does this code mean?

I am trying to figure out what the code below means. I got it from freecodecamp.com and I am doing one of the challenges on there. The challenge is called "Seek and Destroy". I am just one of those people that has to understand what is going on in order for me to proceed, so can someone please explain to me how this code works and what is does from top to bottom?
function destroyer(arr) {
var args = Array.prototype.slice.call(arguments);
return arr.filter(function(element){
return args.indexOf(element) === -1;
});
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
For example, what is the "element" parameter in the function for .filter() method? How does javascript know what "element" is in the first place? I have been asking people and reading descriptions of solutions, but every solution I read is very vague and is still confusing to me.
Side note: I already know the algorithm removes values from arr, but I just want to know how it does it.
var args = Array.prototype.slice.call(arguments);
This line takes all the arguments given in the function and places them into an array. In this case the value is [[1, 2, 3, 1, 2, 3], 2, 3].
return arr.filter(function(element){
...
});
The .filter() function takes an anonymous function which can have three parameters: element, index, and array. In this case the function iterates through the array arr being [1, 2, 3, 1, 2, 3]. For this function if true is returned the element is kept, if false is return the element is removed from the array.
return args.indexOf(element) === -1
Here we check if the array args has the element element. The .indexOf() method returns the index that the element is found, if it's not found -1 is returned. What this means is if the element is not found it returns true, otherwise it will return false (removing it from the array) if it was found.
Basically the above statements means for each element in the array [1, 2, 3, 1, 2, 3] if it's found in [2, 3] then it's removed. It technically checks [[1, 2, 3, 1, 2, 3], 2, 3], but the first check is against an array compared to an element which will always be false so it might as well be omitted.
Below are some brief comments stating what I mentioned above.
function destroyer(arr) {
// An array of the arguments
var args = Array.prototype.slice.call(arguments);
// For every element in the array arr remove elements found in args
return arr.filter(function(element){
return args.indexOf(element) === -1;
});
}

Slicing an Argument on Filter Array?

I have been doing this course for hours on free code camp, however, I found a solution that I do not understand and I am trying to put comments on each line to record as I achieve and understand it for future references and I already understand some lines but I cannot understand some parts of this code:
function destroyer(arr) {
// let's make the arguments part of the array
var args = Array.prototype.slice.call(arguments); // this would result into [[1, 2, 3, 1, 2, 3], 2, 3]
args.splice(0,1); // now we remove the first argument index on the array so we have 2,3 in this example
// I DO NOT UNDERSTAND THESE CODES BELOW
return arr.filter(function(element) {
return args.indexOf(element) === -1;
});
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
I already check on documentation and I find it hard to understand seems the code in this sample are very different. I would really appreciate your help!
arr in the section of code you don't understand refers to the first argument passed to the destroyer function; in this case, the array [1, 2, 3, 1, 2, 3]
arr.filter is using the Array.filter method to create a "filtered" version of the array with only those values that pass the "test" defined by function(element) { return args.indexOf(element) === -1; }
That function uses Array.indexOf to check if the sliced args array (which you correctly identified as being equal to [2, 3]) contains the given element. Because indexOf returns -1 when the element is not found, checking for that value is equivalent to checking that the specified element is NOT in the array
The result of all of this - and the return value of the function destroy - will be the array [1, 1], representing a filtered version of the array passed to destroy that contains all the values not equal to the other values passed to destroy.
Array.slice is part of the arrays prototype;
prototype methods are only accessable on instances of Classes.
var arr = ['a', 'b', 'c', 'd'];
// [] is JavaScript shorthand for instantiating an Array object.
// this means that you can call:
arr.slice(someArg1);
arry.splice(someArg2);

Is it safe to modify an array while looping it?

Is it safe to modify an array while looping it, such as push an element?
I'm using underscore each method
I recommend avoid each unless you absolutely need to cause a side effect for every item in a collection (trigger an event, print out a result, etc.). For simply modifying your collection, there are better ways.
If each added element is only the result of an individual input element, the typical functional pattern would be to flatmap the array, which can be thought of a two steps:
Using map to apply a function that for each element generates an array as a result. The overall result will be an array of arrays.
Using flatten on that array of arrays to get a one dimensional array.
Using underscore or lodash:
var origArray = [1, 2, 3, 4];
var duplicateIf3 = function (val) { return val === 3 ? [val, val] : val; };
_.flatten(origArray.map(duplicateIf3));
// -> [1, 2, 3, 3, 4]
(In typed FP, the function would have to return [val] for values that aren't 3, but flatten doesn't care--it flattens whatever you give it to one dimension.)
If the new element is dependent on all that came before it, you would probably use a reduce or fold instead, with the empty array as the initial value.
var origArray = [1, 2, 3, 4];
origArray.reduce(function (acc, val) { return acc.concat(acc).concat(val); }, []);
// -> [1, 1, 2, 1, 1, 2, 3, 1, 1, 2, 1, 1, 2, 3, 4]
(Sorry I couldn't think of a realistic example, but here every step uses the full output of all previous steps in a pretty simple way for illustrative purposes, and you can see from each value of the original array what's going on. Also note that you can make your own flatten from reduce, if you don't want to use underscore/lodash)
reduce is more general than flatmap, but both methods are able to convert an array into a larger array that some how depends on the first one.
If you're interested in learning more about this, I highly recommend checking out the free (online) Javascript Allongé, by Reg Braithwaite.
I'm not sure what you mean by safe, but you'd have to have a good reason to do it. I played around with it a bit, and here's what I got:
_.each(a, function(el) {
if (el % 2 == 0)
a.push(el + 1);
console.log(el);
});
// logs 1, 2, 3, 4, 5
console.log(a);
// logs [ 1, 2, 3, 4, 5, 3, 5 ]
In this case, there is no negative affect unless you wanted to go through the added elements, but you could find yourself in trickier situations if you're changing the specific elements:
_.each(a, function(el, index) {
a[index + 1] = el - 1;
if (el % 2 == 0)
a.push(el + 1);
console.log(el);
});
// logs 1, 0, -1, -2, -3
It would make more sense to use _.map for most use cases.

Categories

Resources