Let's simplify things by ignoring the wrapper object. How about trying this?
const data = [
[1, 'asdf'],
[2, 'lorem'],
[3, 'impsum'],
[4, 'test'],
[5, 'omg'],
];
const out = data.map(([ num, ...rest ]) => {
return Array(4).fill(0).map((_, idx) => {
return [ num + ((idx + 1) / 10), ...rest ];
});
}).flat(1);
console.log(out);
You could condense it into a one-liner if you really wanted to! *
data.map(([ num, ...rest ]) => Array(4).map((_, index) => ([ num + ((index + 1) / 10), ...rest ]))).flat(1);
* But please don't.
UPDATE: Let me break down the code above since there are multiple actions happening within those few lines.
We kick things off with a call to Array.map
:
data.map((...) => { ... })
This operation creates a new array that matches the length of data
, with each element being processed through the arrow function (a more concise way of writing function(...) { ... }
) before being inserted into the new array.
Before delving into the body of the function, let’s examine its parameter more closely:
([ num, ...rest ]) => { ... }
// Alternatively in regular function format:
function ([ num, ...rest ]) { ... }
In this setup, we make use of both array destructuring and spread syntax. These two features, introduced in ES6, bring significant power to JavaScript. Array destructuring assigns values from an array directly to individual variables without needing an intermediate variable to store the entire array.
The function here only takes one argument (an array), but surprisingly, we have access to two variables within the function body. However, neither one represents the entirety of the array.
- The first variable is
num
, which holds the value of the initial element in the array.
- The second variable is
rest
, containing all remaining values in the array except the first one (which is stored in num
). The spread syntax signifies “the rest of the values”, aggregating all elements following the first into rest
.
Inside the mapping function, our starting point looks like this:
Array(4)
Array()
serves as the constructor for JavaScript's underlying Array
type. When provided with a single numerical argument, it initializes the array to that size.
We then proceed to apply Array.map()
once again on the newly created array:
Array(4).map((_, idx) => { ... })
Note that this time, the function passed into map
involves two parameters: _
and idx
. Similar to before, the former represents the current element under processing within the array. Given that the array is currently empty, we disregard this element (hence naming it like so). The latter indicates the index of the present element within the array, crucial for calculating the updated value of num
:
num + ((idx + 1) / 10)
This expression merges the original value of num
for this particular set of new elements with the fractional part based on the current position in the inner array.
The modified num
gets returned alongside the other values stored previously in rest
:
return [ num + ((idx + 1) / 10), ...rest ];
Here, we solicit the spread operator again, implying that not just another array be returned as an element in the array, but rather each component within rest
should get appended to the resulting array.
Hence, this complete internal section furnishes an array of arrays for a single fresh ‘group’ of elements:
return Array(4).map((_, idx) => {
return [ num + ((idx + 1) / 10), ...rest ];
});
// Representation Upon Return:
[
[ 1.1, "asdf" ],
[ 1.2, "asdf" ],
[ 1.3, "asdf" ],
[ 1.4, "asdf" ],
]
Reinserting the outer cover yields:
data.map(([ num, ...rest ]) => {
return Array(4).fill(0).map((unused, idx) => {
return [ num + ((idx + 1) / 10), ...rest ];
});
})
// Resultant Scenario:
[
[
[ 1.1, "asdf" ],
[ 1.2, "asdf" ],
[ 1.3, "asdf" ],
[ 1.4, "asdf" ],
],
[
[ 2.1, "lorem" ],
[ 2.2, "lorem" ],
[ 2.3, "lorem" ],
[ 2.4, "lorem" ],
],
...
]
All pertinent values have been correctly deduced, however, an unwanted extra stratum of arrays exists here. Most likely, you've identified the final chunk of code already:
.flat(1)
Array.flat()
performs an elevation on the array according to a specified depth. A depth setting of 1
leads to every array being immediately inside the outer array getting their components incorporated into said outer array. For a depth value of n
, this procedure recurs upon the output of the prior iteration exactly n
times. Opting for a depth of
2</code in this situation would yield a solitary array structured thusly:</p>
<pre class="lang-js"><code>[ 1.1, "asdf", 1.2, "asdf", ... ]