Strange map behaviour [duplicate] - javascript

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));

Related

JavaScript array map: callback vs arrow function [duplicate]

This question already has answers here:
Shortcut of calling a method without writing parameters in Javascript
(4 answers)
What is .map() doing in this situation?
(4 answers)
Closed 1 year ago.
I ran into an issue regarding array mapping functions in JS and cannot explain why this is happening, nor do I find any helpful search results with an explanation. Sorry if this was posted already somewhere.
Could anyone explain why the results differ?
const [ i, j ] = "1x2".split('x').map((value) => parseInt(value));
console.log(i);
console.log(j);
const [ i, j ] = "1x2".split('x').map(parseInt);
console.log(i);
console.log(j);
cheers
parseInt receives as second argument the radix:
radix Optional
An integer between 2 and 36 that represents the radix (the base in mathematical numeral systems) of the string. Be careful—this does not default to 10! If the radix value is not of the Number type it will be coerced to a Number.
So, when you do:
const [ i, j ] = "1x2".split('x').map(parseInt);
it is the same like:
const [ i, j ] = "1x2".split('x').map((value, index) => parseInt(value, index));
(the map callback is called with currentValue, currentIndex and arrayReference)
Hence, parseInt("2", 1) is NaN because 1 is not a valid radix value.

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...

Fastest way to fill an array with multiple value in JS. Can I pass a some pattern or function to method fill insted of a single value in JS? [duplicate]

This question already has answers here:
Does JavaScript have a method like "range()" to generate a range within the supplied bounds?
(88 answers)
Closed 4 years ago.
Is it any way to create an array a selected size(for example 10) and immediately on the spot fill in it with some numbers specified pattern (1, 2, 3, OR 2, 4, 6 and so on) in one statement in JS?
let arr = new Array(10).fill( (a) => {a = 1; return a++; } );
console.log(arr); // Should be 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
In other words can I pass a some patern or function to method fill insted of a single value.
Actually there's much nicer idiom to create ranges: a spreaded Array constructor:
[...Array(n)]
creates an array of n undefined values. To get 0..n-1, just pick its keys:
[...Array(n).keys()]
for arbitrary ranges, feed it to map:
r = [...Array(10)].map((_, i) => i + 1)
console.log(r)
see here: Does JavaScript have a method like "range()" to generate an array based on supplied bounds?
old answer:
yep, you're looking for Array.from:
r = Array.from({length: 10}, (_, i) => i + 1);
console.log(r)
How does this work? .from inspects its first argument (which can be any object) and picks its .length property. Then, it iterates from 0 to length - 1 and invokes the second argument with two parameters - a value (which is undefined unless the first argument contains a corresponding numeric property) and an index, which takes values from 0...length-1. In this example, we have a function that just returns an index + 1, thus giving us 1..length.
Here's a useful wrapper for the above:
let range = (from, to) => Array.from({length: to - from + 1}, _ => from++);
console.log(range(1, 10))
For ES5, the idiom is Array.apply(null, {length:N}):
r = Array.apply(null, {length: 10}).map(function(_, i) {
return i + 1
})

Manufacturing an array - why is it different? [duplicate]

This question already has answers here:
JavaScript "new Array(n)" and "Array.prototype.map" weirdness
(14 answers)
Closed 5 years ago.
consider I declare two variables like this (done within REPL, with node v7.7.2), which I expect to be arrays:
var x = Array(4)
var y = Array.from({length: 4})
then the following should work identically, but it doesn't:
x.map(Math.random)
[ , , , ]
y.map(Math.random)
[ 0.46597917021676816,
0.3348459056304458,
0.2913995519428412,
0.8683430009997699 ]
in looking, it seems x and y are both identical:
> typeof x
'object'
> typeof y
'object'
> Array.isArray(x)
true
> Array.isArray(y)
true
> x.length
4
> y.length
4
> typeof x[0]
'undefined'
> typeof y[0]
'undefined'
so why the difference?
Actually, it should not have the same results fot both cases. See the manual here about Array:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
If the only argument passed to the Array constructor is an integer
between 0 and 232-1 (inclusive), this returns a new JavaScript array
with its length property set to that number (Note: this implies an
array of arrayLength empty slots, not slots with actual undefined
values). If the argument is any other number, a RangeError exception
is thrown.
And here about the Array.from() method
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/from
Check the following example on the page linked above:
// Generate a sequence of numbers
// Since the array is initialized with `undefined` on each position,
// the value of `v` below will be `undefined`
Array.from({length: 5}, (v, i) => i);
// [0, 1, 2, 3, 4]
For the first three outputs, Array#map works.
It is not called for missing elements of the array (that is, indexes that have never been set, which have been deleted or which have never been assigned a value).
The ECMA 262 standard to Array.from describes a construction with length for a new array (point 7 ff).
var x = Array(4),
y = Array.from({ length: 4 }),
arrayX = x.map(Math.random),
arrayY = y.map(Math.random),
z = Array.from({ length: 4 }, Math.random);
console.log(x);
console.log(y);
console.log(arrayX);
console.log(arrayY);
console.log(z);
The Array created with Array(4) is not iterated over with .map(), whereas the Array.from({ length: 4 }) is iterated over. A fuller explanation can be found at JavaScript "new Array(n)" and "Array.prototype.map" weirdness, you can test this with..
x.map((f,i) => console.log(i)) vs. y.map((f,i) => console.log(i))

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

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);

Categories