Why there is a difference in map() output in the below code?
var y = [1,2,2,1];
var t = y.map(ind => [...Array(ind)].map((_,i) => ind+""+i));
// This makes [ [ '10' ], [ '20', '21' ], [ '20', '21' ], [ '10' ] ]
var t1 = y.map(ind => Array(ind).map((_,i) => ind+""+i));
//[ [ <1 empty item> ], [ <2 empty items> ], [ <2 empty items> ], [ <1 empty item> ] ]
This is basically the reason you should avoid using the Array constructor to create arrays.
When passed a single number n as an argument, the Array constructor will return an array with length n, but no elements, also known as a sparse array. (Anything else passed to the Array constructor, a string, an object, two numbers, etc, will create a normal array with the passed arguments as elements in order).
Trying to .map() over this array will not work, since there are no items in it, which is why you get the same sparse arrays. Your .map() is a no-op.
Using [... (Same with Array.from(), by the way) on it, will "realize" the array turning [ <1 empty item> ] into [undefined] and [ <2 empty items> ] into [undefined, undefined], an array with actual elements, whose values are undefined. .map() does work on this, so you get the result you expect.
In short, avoid the Array constructor.
Related
I want to convert this:
[null, 1890, null, NGU]
...into this:
[[], [1890], [], [NGU]]
I've tried creating a new array and pushing values to it, but that just ends up looking the same. Honestly, I'm unsure of what to even call what I'm trying to create. Is it a two-dimensional array or an array of objects?
This is for a google app script and the documentation calls it a two-dimensional array of values.
var arr = [null, 1890, null, 'NGU']
var arr2d = arr.map(x => [x])
console.log(arr2d) // output --> [ [ null ], [ 1890 ], [ null ], [ 'NGU' ] ]
This question already has answers here:
Array.fill(Array) creates copies by references not by value [duplicate]
(3 answers)
Closed 1 year ago.
Recently, I was trying to create three-level deep nested arrays. Crazy, I know, but it was the best solution to my problem I could think of. The arrays are created with the following code.
const lengths = [2, 3];
const arrays = lengths.map((v, i) => {
return Array(lengths[i]).fill([]);
});
arrays[0][0].push(1);
console.log(arrays);
// Expected: [ [ [ 1 ], [] ], [ [], [], [] ] ]
// Actual: [ [ [ 1 ], [ 1 ] ], [ [], [], [] ] ]
As you can see, I only push to array[0][0]. Yet, both [0][0] and [0][1] get pushed to. What is going on here? Is it a bug, or a feature? Some kind of weird memory management?
If it helps, I am using Node.js. Thanks in advance.
You are filling the entire array with the same array reference. Instead, you could use the mapping callback of Array.from to rectify this issue by returning a different array each time.
const lengths = [2, 3];
const arrays = lengths.map((v, i) => {
return Array.from({length: lengths[i]}, _=>[]);
});
arrays[0][0].push(1);
console.log(arrays);
.as-console-wrapper{top:0;max-height:100%!important}
I have an array of arrays of data returning to me back from a csv file. I am attempting to filter out each index of an array depending on which title is in the array. For example:
If an index of the array has the name "Retail" return that entire index which includes some values.
Here is my array :
[
[
"Retail",
"22,477",
"24,549",
"19,580",
"15,358",
],
[
"Online",
"8,653",
"7,586",
"2,432",
"4,321"
],
[
"In Store",
"2,532",
"2,836",
"5,632",
"7,325"
]
]
I've attempted these two separate ways and both are returning an array of 0:
filtArr = dataList.filter(name => name.includes('Retail')) //expecting the array length 5 with "Retail" and it's values
attempt 2
filtArr = dataList.filter(function (name) {
return (name === "Retail")
})
Expected return is: console.log(filtArr) // [ 0. "Retail", 1. "22,477", 2. "24,549", 3. "19,580", 4. "15,358"
A good way to check if an array contains some item is to test it with the indexOf method.
It will return -1 if the item is not found or else its index.
You could do this to store all arrays containing 'Retail' in them:
let retailArrays = [];
arrayOfArrays.forEach(
array => {
if( array.indexOf('Retail') !== -1) {
retailArrays.push(array);
};
}
)
You apparently have trailing spaces after some of the names, so maybe "Retail" is actually "Retail ".
It also looks like the name is always the first element of the nested array, so there's no need to search the whole array.
So use trim() on the first element to remove the surrounding spaces.
filtArr = dataList.filter(arr => arr[0].trim() == 'Retail');
var dataList = [
[
"Retail",
"22,477",
"24,549",
"19,580",
"15,358",
],
[
"Online",
"8,653",
"7,586",
"2,432",
"4,321"
],
[
"In Store",
"2,532",
"2,836",
"5,632",
"7,325"
]
];
filtArr = dataList.filter(arr => arr[0].trim() == 'Retail');
console.log(filtArr);
is my understanding of arrays inside of arrays is built like this?
a = new Array[
b = new Array[
c = new Array[
something,
something.more,
something.more.to,
something.more.to.learn
]]];
or does it need to be
a = new Array[];
a.b = new Array[];
a.b.c = new Array[
a.b.c.something,
a.b.c.something.more,
a.b.c.something.more.to,
a.b.c.something.more.to.learn
];
or am I as lost as I think I am.
You need to differentiate between arrays and objects.
You may use arrays like so:
var nested = new Array(
new Array( '1.1', '1.2' ),
new Array( '2.1', '2.2' ),
);
Or use the short syntax:
var nested = [ [ '1.1', '1.2' ], [ '2.1', '2.2' ] ];
But you can't access array items by a textual index like in PHP or the like, you need to refer to the numbered index to call the different elements.
// Alert the first value of the second array in nested.
// Note that array indeces start off on zero.
alert( nested[ 1 ][ 0 ] ); // -> 2.1
If you need to reference the different elements you have to use objects:
var nested = {
first: {
a: '1.1',
b: '1.2'
},
second: {
a: '2.1',
b: '2.2'
}
}
alert( nested.second.a ); // -> 2.1
You can define multi-dimensional arrays a couple different ways but if you want inline, this would be a very simple way. (This is just a random structure for example purposes)
var arr =
[
["a"],
[
["b"],
[],
[
["c"]
]
],
[
[],
[]
]
];
Things get really hard to follow but just treat each tab in as a sub dimension of the parent array.
To access any element you would use indexes
arr[0][0]; // "a"
arr[1][0][0]; // "b"
arr[1][2][0][0]; // "c"
This really helps when you have intracate structures where delcaring new Array(...) would get very chained and complicated.
I am trying to test if my deep clone of an array is identic to the original object (jQuery available).
Here is how I clone it
self.slides = jQuery.extend(true, {}, parent.modules[self.moduleId].composed);
However, I end up with two slightly different objects, so even if the actual content that I am concerned with is identic, these two objects aren't. If I dump them in chrome console, this is how they look:
Original object:
[Object]
0: Object
length: 1
__proto__: Array[0]
Clone:
Object {0: Object}
0: Object
__proto__: Object
So the clone appears to actually be an object (or an object of type object) while the original seem to be an array (or object of type array).
Is there another way of cloning or how can I perform this identic-test?
Simplest way to clone any object would be
var array1 = [1, [2], 3];
var array2 = JSON.parse(JSON.stringify(array1));
You can check them like this
console.log(array1, array2);
// [ 1, [ 2 ], 3 ] [ 1, [ 2 ], 3 ]
array1[1][0] += 3;
console.log(array1, array2);
// [ 1, [ 5 ], 3 ] [ 1, [ 2 ], 3 ]
this occurs because you are passing an object "{}" extender to try to clone this way, I believe it is much better
var clone = myArray.slice(0);