parseInt misbehaves when passed as argument to a map call [duplicate] - javascript

This question already has answers here:
Why does parseInt yield NaN with Array#map?
(8 answers)
Closed 9 years ago.
Why is this happening?
var numbers = [ '1', '2', '3', '4' ];
var intNumbers = numbers.map( parseInt ); // intNumbers = [1, NaN, NaN, NaN]
var fltNumbers = numbers.map( parseFloat ); // fltNumbers = [1, 2, 3, 4, 5 ]
But Array.prototype.map.call( numbers, parseInt ); returns [ 1, 2, 3, 4];. I'm running this code in Google Chrome 26.0.1410.65.

The link to proper answer is given in comments, but i want to post it here
:
["1", "2", "3"].map(parseInt);
While one could expect [1, 2, 3]
The actual result is [1, NaN, NaN]
parseInt is often used with one argument, but takes two. The second
being the radix To the callback function, Array.prototype.map passes 3
arguments: the element, the index, the array
The third argument is ignored by parseInt, but not the second one, hence the possible confusion.
Quick fix
function returnInt(element){
return parseInt(element,10);
}
["1", "2", "3"].map(returnInt);
Actual result is an array of numbers (as expected)

https://developer.mozilla.org/en-GB/docs/JavaScript/Reference/Global_Objects/Array/map explains how map works.
I find it easier with the solution that jonah proposed, create a returning function for thing you want to map instead of tossing it..
intN = numbers.map(function(i) { return parseInt(i) });
The real reason is that you are trying to feed a function to map, but JS is not getting the function properly.
You better declare the function first and then feed it.
var titi = function(i) { return parseInt(i); };
var intN2 = numbers.map(titi);

Related

filter and includes in array, how does that work?

I'm trying to understand how filter() and includes() work with arrays in javascript but english isn't my native language so I would really appreciate it if someone could explain the example below to me like I was 5:
const removeFromArray = function(...num) {
let array = num[0];
return array.filter(val => !num.includes(val))
};
This function takes an array and some other arguments then removes the other arguments from that array for example removeFromArray([1, 2, 3, 4], 3) should remove 3 and return [1,2,4]
How does this part work?
return array.filter(val => !num.includes(val))
Why the exclamation mark and also how do those two methods work together?
I think the key to understanding what is going on is the parameter(s) of the function, num. The code uses a nice trick that I have not encountered before. So, num is:
[[1, 2, 3, 4], 3];
a 1D array with TWO elements: [1, 2, 3, 4] at index 0, and 3 at index 1. As a result:
num.includes([1, 2, 3, 4]) // is true
num.includes(3) // is true
num.includes(anything-else) // is false
The
Array#includes
method determines whether an array includes a certain value among its
entries, returning true or false as appropriate.
In the simplest form, whenever a boolean expression is prefixed with !, the result of the expression is negated. For example:
!num.includes(3) // becomes false
The
Array#filter
method creates a new array with all elements that pass the test
implemented by the provided function.
Pass the test simply means return true.
Now we are ready to look at num[0].filter(val => !num.includes(val)). Or:
[1, 2, 3, 4].filter(val => !num.includes(val))
Please recall that ONLY 3 and [1, 2, 3, 4] return true to:
num.includes(val)
Hence of all the elements of num[0] or [1, 2, 3, 4] only 3 returns false to the negated expression:
!num.includes(val)
1, 2, and 4 return true or !false, meaning that they pass the test and hence will be returned by the function:
[1, 2, 4];
Please note that val => !num.includes(val) is a shorthand way of writing:
function( val ) {
return !num.includes(val);
}
const removeFromArray = function(...num) {
let array = num[0];
return array.filter(val => !num.includes(val))
};
console.log( removeFromArray([1, 2, 3, 4], 3) );
Rest parameters shouldn't be used like that, it should only be used for like values. So, the array should be accepted separately and only the numbers to remove should be accepted using rest (refer to the snippet below).
The includes() method determines whether an array includes a certain value among its entries, returning true or false as appropriate.
So, we simply filter out numbers that are not present in the itemsToRemove array.
const removeFromArray = (array, ...itemsToRemove) =>
array.filter((item) => !itemsToRemove.includes(item));
removeFromArray([1, 2, 3, 4], 3, 2);
! means "not". If something is falsy (null, 0, false, an empty string), then !something returns true. This leads to a really strange looking "cheat code" where you can convert any value to a boolean (i.e. truthy to true and falsy to false) via !!value. One exclamation point converts it to a boolean value that's true if value is falsy, then the second exclamation point changes true to false (or false to true)!
array.prototype.filter requires a function to be evaluated against each element and returns an array of only the elements where the supplied function returns a truthy value.
It might be easier to think of the following code that is nearly equivalent to yours...
const removeFromArray = function(array, ...valsToRemove) {
const isValToKeep = val => array.includes(val) === false;
return array.filter(isValToKeep)
};
The only difference in this code, besides being longer, is that the first argument won't be looked for within the first argument. Consider
const a1 = [1,2,3];
a1.push(a1); // appends itself as its last element
In your version, removeFromArray(a1, 2) would return [1, 3], but mine doesn't combine the first argument as one of the elements to look for and remove from the first argument, which is probably what most people would expect and be more performant, but would definitely have a different effect in the example returning [1, 3, a1], i.e. [1, 3, [1, 2, 3, [1, 2, 3, [1, 2, 3, [1, 2, 3, [1, 2, 3, [1, 2, 3, [...]]]]]]]]
This is a simple form to explain how to use filter
function isBigEnough(value) {
return value >= 10;
}
var filtered = [12, 5, 8, 130, 44].filter(isBigEnough);
// result is [12, 130, 44]
This example is from: https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
Lets start by rewriting this line:
Before
return array.filter(val => !num.includes(val))
after
const callback = val => {
return !num.includes(val)
}
const filteredArray = array.filter(callback);
return filteredArray
Now lets break and explain parts of this statement:
! num.includes(val)
includes method here will check if num has val in it. If num has val it will return true else it will return false. note the ! at the begining of the line ,that will change the value returned by includes to its opposite e.g if value returned is false it will change it to true if value returned is true it will change it to false.
array.filter(callback)
The filter method here will go through every element of the array and at each element it will ask whether to add that element to the filteredArray or not based on what is returned from the callback. If callback returns true(truthy) it will add it else it will not add it. The callback should only return true(truthy) or false(falsy).
example :
At index 0 of array the filter will ask did callback return true if it returned true the element at index 0 will be added to the filtered array. It will do the same for the rest of the elements.
How they work together:
array has [1,2,3,4] so array.filter(callback) will go over each element and call callback on each. Based on your function num has this [[1,2,3,4],3] so when val from array is 3 !num.includes(val) will return true but this ! will change it to false as a result callback will return false and 3 will not be included in the final array the filteredArray.
Hope a 5 year old can understand this explantion. You can now rewrite your function like this :
const removeFromArray = (array, ...numbersToRemove) => array.filter((number) => !numsToRemove.includes(number));

Concatenating Numbers in javascript [duplicate]

This question already has answers here:
Javascript Concatenate Array to String
(2 answers)
Closed 2 years ago.
My goal is to make numbers into strings.
If my actual = concatenateNumbers(7);
expected = "7"
My code for this would be:
function concatenateNumbers(num1) {
return num1.toString();
}
However, if my actual has 2 or 3 more values, actual = concatenateNumbers(7, 9) or actual = (7, 9 ,1) => the expected is = "79" or "791"
Can anybody give me an idea or hint on how I should approach this?
Use The arguments object converted to a real Array, and use Array.prototype.join() with an empty String:
function concatenateNumbers() {
return [...arguments].join("");
}
var numbersArrays = [
[],
[7],
[7, 9],
[7, 9, 1]
];
numbersArrays.forEach(numbersArray=>{
console.log(numbersArray.join(", ") + " => " + concatenateNumbers(...numbersArray));
});
console.log("1, 2, 3 => "+concatenateNumbers(1, 2, 3));
numbersArrays is just a convenient way to use SO's code snippet, along with "["+numbersArray.join(", ")+"]" to show each numbersArrays's Array as an Array, plus the actual call to the actual function concatenateNumbers.
Edited to make function's arguments actually a list of Numbers using the Spread syntax (...), as pointed out by VLAZ.
It will actually concatenate anything, the best it can...

Strange map behaviour [duplicate]

This question already has answers here:
Why does parseInt yield NaN with Array#map?
(8 answers)
Closed 6 years ago.
What is the difference between map(func) and map(function(x) { return func(x); })?
Consider this example:
const lines = '1\n2\n3';
const result = lines.split('\n').map(parseInt);
console.log(result )
This returns [1, NaN, NaN] which is not what I expected.
However:
const lines = '1\n2\n3';
const result = lines.split('\n').map(function(x){ return parseInt(x)});
console.log(result)
returns the expected: [1, 2, 3]. What is the difference between these two forms and why in the first example the result is not [1, 2, 3]?
parseInt has a second parameter (radix).
Basically you perform this
value index parseInt comment
----- ----- -------- -----------------------------------------------------
'1' 0 1 with radix 0, and value 1 parseInt assumes radix = 10
'2' 1 NaN because of the wrong value for the radix
'3' 2 NaN because of the wrong value for the radix
For converting to a number, you could use Number.
var lines = '1\n2\n3'
console.log(lines.split('\n').map(Number));
For getting integer values, you could use Math.floor as well.
var lines = '1\n2\n3'
console.log(lines.split('\n').map(Math.floor));
The difference is that .map passes to its function 3 parameters:
.map(element, index, array)
when the parseInt function accepts 2 arguments
parseInt(string, radix)
So, you pass index as a radix. That is why your result is wrong. If parseInt was accepting just one argument it would work.
Because the index from the map will be passed into the map function
let lines = '1\n2\n3'
let a = lines.split('\n').map(parseInt);
console.log(a)
// Your code above is expanded as below
a = lines.split('\n').map((x, i) => {
return parseInt(x, i)
})
console.log(a)
// To fix it, use this
lines.split('\n').map(x => parseInt(x));

Spread Syntax vs Rest Parameter in ES2015 / ES6

I am confused about the spread syntax and rest parameter in ES2015. Can anybody explain the difference between them with proper examples?
When using spread, you are expanding a single variable into more:
var abc = ['a', 'b', 'c'];
var def = ['d', 'e', 'f'];
var alpha = [ ...abc, ...def ];
console.log(alpha)// alpha == ['a', 'b', 'c', 'd', 'e', 'f'];
When using rest arguments, you are collapsing all remaining arguments of a function into one array:
function sum( first, ...others ) {
for ( var i = 0; i < others.length; i++ )
first += others[i];
return first;
}
console.log(sum(1,2,3,4))// sum(1, 2, 3, 4) == 10;
ES6 has new feature three dots ...
Here is how we can use these dots:
As Rest/Collector/Gather
var [c, ...m] = [1,2,3,4,5]; // m -> [2,3,4,5]
Here ...m is a collector, it collects the rest of the parameters. Internally when we write:
var [c, ...m] = [1,2,3,4,5];
JavaScript does following
var c = 1,
m = [2, 3, 4, 5];
As Spread
var params = [ "hello", true, 7 ];
var other = [ 1, 2, ...params ]; // other => [1,2,"hello", true, 7]
Here, ...params spreads so as to adding all of its elements to other
Internally JavaScript does following
var other = [1, 2].concat(params);
Summary:
In javascript the ... is overloaded. It performs a different operations based on where the operator is used:
When used in function arguments of a function declaration/expression it will convert the remaining arguments into an array. This variant is called the Rest parameters syntax.
In other cases it will spread out the values of an iterable in places where zero or more arguments (function calls) or elements (array literals) are expected. This variant is called the Spread syntax.
Example:
Rest parameter syntax:
function rest(first, second, ...remainder) {
console.log(remainder);
}
// 3, 4 ,5 are the remaining parameters and will be
// merged together in to an array called remainder
rest(1, 2, 3, 4, 5);
Spread syntax:
// example from MDN:
function sum(x, y, z) {
return x + y + z;
}
const numbers = [1, 2, 3];
// the numbers array will be spread over the
// x y z parameters in the sum function
console.log(sum(...numbers));
// the numbers array is spread out in the array literal
// before the elements 4 and 5 are added
const newNumbers = [...numbers, 4, 5];
console.log(newNumbers);
Javascript's three dots ( ... ) operator can be used in two different ways:
Rest parameter: collects all remaining elements into an array.
var days = ["Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri"];
const [sat, sun, ...weekdays] = days;
console.log(sat); // "Sat"
console.log(sun); // "Sun"
console.log(weekdays); // ["Mon", "Tue", "Wed", "Thu", "Fri"]
Spread operator: allows iterables( arrays / objects / strings ) to be expanded into single arguments/elements.
var weekdays = ["Mon", "Tue", "Wed", "Thu", "Fri"];
var days = [...weekdays, "Sat", "Sun"];
console.log(days) // ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
Note that the spread operator can be the first element, but the rest parameter needs to be the last to collect the rest elements .
When we see "..." in the code, it is either rest parameters or the
spread operator.
There’s an easy way to distinguish between them:
When ... is at the end of function parameters, it’s “rest parameters”
and gathers the rest of the list into the array. When ... occurs in a
function call or alike, it’s called a “spread operator” and expands an
array into the list. Use patterns:
Rest parameters are used to create functions that accept any number of
arguments. The spread operator is used to pass an array to functions
that normally require a list of many arguments. Together they help to
travel between a list and an array of parameters with ease.
For more information about this click here
Added in ES6 these three dots ... has two meanings, Spread operator and Rest parameter
Spread operator: You use the three dots to expand iterables, by iterables I mean arrays, string, etc. As arguments. For example Math.max() function expect an indeterminate number of arguments so you can use Spread operator to expand elements as arguments on Math.max() function. Here an example from mdn
console.log(Math.max(1, 3, 2));
// expected output: 3
console.log(Math.max(-1, -3, -2));
// expected output: -1
var array1 = [1, 3, 2];
console.log(Math.max(...array1));
// expected output: 3
Another use case is to add, for example having this array
const videoGames = ['mario galaxy', 'zelda wind waker', 'ico'];
You can add it to another array
const favoritesVideoGames = ['Shadow of the colosus', ...videoGames];
Then favoritesVideoGames value is
[ 'Shadow of the colosus', 'mario galaxy', 'zelda wind waker', 'ico' ]
About Rest parameter, here the MDN definition
The rest parameter syntax allows us to represent an indefinite number
of arguments as an array.
This means you can pack many elements into a single element
Here an example from MDN
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
I usually get confused with these three points, this illustration by #stephaniecodes helps me to remember its logic. I mention that I took inspiration from this illustration to answer this question.
I hope it is useful.
Basically like in Python:
>>> def func(first, *others):
... return [first, *others]
>>> func('a', 'b', 'c')
['a', 'b', 'c']
Simple to remember ............
if the triple dots (...) are on the left side its Rest paramenter, if the triple dots are on the right side its Spread parameter.
const [a,b,...c] = [1,2,3,4,5] // (left) rest
const [d,e] = [1, ...c] // (right) spread
In reference to this i cant understand how we are passing a function and returning arguments in javascript
Function is a set of instructions that takes some input and processes them and returns result.
here we have an array [1, 2, 3, 4, 5, 6], and filter function iterates over each element and passes each element to positive functions which returns the number if it is even, else skips it.
trace:
1 => Filter(1) => positive(1) => skips 1,
2 => Filter(2) => positive(2) => returns 2,
3 => Filter(3) => positive(3) => skips 3,
...
6 => Filter(6) => positive(6) => returns 6
hence the result
[2, 4, 6]
considering 3 scenarios
1] without using any operator
function add(x, y) {
return x + y;
}
add(1, 2, 3, 4, 5) // returns 3 (function will takes first 2 arg only)
2] with rest operator
function add(...args) {
let result = 0;
for (let arg of args) result += arg;
return result
}
add(1) // returns 1
add(1,2) // returns 3
add(1, 2, 3, 4, 5) // returns 15
- we can gather any number of arguments into an array
3] with spread operator
const arr = ["Joy", "Wangari", "Warugu"];
const newArr = ["joykare", ...arr];
The value of newArr will be [ 'joykare', 'Joy', 'Wangari', 'Warugu' ]
another one
function add(a, b, c) {
return a + b + c ;
}
const args = [1, 2, 3];
add(...args);
-We have been using arrays to demonstrate the spread operator,
but any iterable also works. So, if we had a
string const str = 'joykare', [...str] translates to [ 'j', 'o', 'y', 'k', 'a', 'r', 'e' ]
From: Ved Antani, Stoyan Stefanov Book “Object-Oriented JavaScript - Third Edition.” :
Rest parameters
ES6 introduces rest parameters. Rest parameters allow us to send an arbitrary number of parameters to a function in the form of an array. Rest parameter can only be the last one in the list of parameters, and there can only be one rest parameter. Putting a rest operator(...) before the last formal parameter indicates that parameter is a rest parameter. The following example shows adding a rest operator before the last formal parameter:
function sayThings(tone, ...quotes){
console.log(Array.isArray(quotes)); //true
console.log(`In ${tone} voice, I say ${quotes}`)
}
sayThings("Morgan Freeman","Something serious","
Imploding Universe"," Amen");
//In Morgan Freeman voice, I say Something serious,
Imploding Universe,Amen
The first parameter passed to the function is received in tone, while the rest of the parameters are received as an array. Variable arguments (var-args) have been part of several other languages and a welcome edition to ES6. Rest parameters can replace the slightly controversial arguments variable. The major difference between rest parameters and the arguments variable is that the rest parameters are real arrays. All array methods are available to rest parameters.
Spread operators
A spread operator looks exactly like a rest operator but performs the exact opposite function. Spread operators are used while providing arguments while calling a function or defining an array. The spread operator takes an array and splits its element into individual variables. The following example illustrates how the spread operator provides a much clearer syntax while calling functions that take an array as an argument:
function sumAll(a,b,c){
return a+b+c
}
var numbers = [6,7,8]
//ES5 way of passing array as an argument of a function
console.log(sumAll.apply(null,numbers)); //21
//ES6 Spread operator
console.log(sumAll(...numbers))//21

Split string in javascript into an array

I am using the eval() function to create an calculator, and as you know eval returns a string (I am referring to this tutorial), for example 20+30. What I want now is to split this string so I will have an array of data like [20,30,50] where the 20 and 30 are the operands and 50 is the result in this case.
What I did so far is:
var input = document.getElementById('screen');
var result= '20+30'; // as an example
var firstOperand = result.split('+', 1); //this is taking the first operand
What I really want is as I mentioned to turn my input value that is string "20+30" to an array: myArr = [20,30,50].
Any help?
Use the power of maps and reduce!
result = '1+2+3+4+5+6+7+8+9';
a = result.split('+').map(function(x){ return parseInt(x) });
b = a;
b.push(a.reduce(function(p, c) { return p+c; }));
// b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 45]
Btw you shouldn't use eval(), look into the Shunting-yard algorithm instead. Code examples for the algorithm can be found here at SO and at Rosettacode.
you can create the array passing to the split function only the separator.
var myArr = result.split('+');
now you need to add the result:
myArr.push("50");

Categories