2

I want to create a multi-dimensional array like this using Lodash or vanilla JS:

[
  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
  [11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
  etc
]

This is a simplistic example since I want this pattern to continue up to 1,000,000 but for demonstration 1 to 20 is fine.

Any ideas? I've tried _.range(20) so far but I need this Array to be multi-dimensional. Thanks

danday74
  • 52,471
  • 49
  • 232
  • 283
  • What happened when you tried `_.range(20)`? Perhaps you'd then be interested in [`_.chunk()`](https://lodash.com/docs/4.17.10#chunk) – Phil Nov 20 '18 at 23:54
  • 1
    Pure JS: `Array.from(new Array(30)).map((_, i) => i + 1).reduce((acc, v) => v % 10 === 1 ? [...acc, [v]] : (acc[Math.floor((v - 1) / 10)].push(v), acc), [])` – zerkms Nov 20 '18 at 23:58

4 Answers4

5

With lodash you can use chunk:

const result = _.chunk(_.range(1, 21), 10);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
slider
  • 12,810
  • 1
  • 26
  • 42
5

Using nested native Array#from()

const 
   limit = 100,
   fr = Array.from;

const res = fr({ length:limit/10 }, (_,i) => fr({ length:10 }, (_,j) => i*10 + j+1 ));

console.log(res)
charlietfl
  • 170,828
  • 13
  • 121
  • 150
  • 1
    `Array#from()` spot the Java dev ;-) – Phil Nov 21 '18 at 00:05
  • I know OP doesn't mention, but what if the `limit` isn't a multiple of 10, say 25? [Slider's answer](https://stackoverflow.com/a/53403380/283366) handles that case via chunking – Phil Nov 21 '18 at 00:07
  • @Phil right...I assumed even 10's based on 20 and 1,000,000 – charlietfl Nov 21 '18 at 00:09
  • 2
    It's not as pretty, but you could have something like `{length:Math.min(10, limit-(i*10))}` in the inside loop to handle non-even groupings. – Mark Nov 21 '18 at 00:16
  • @Akrion me too...never noticed that range generator example until I saw it in yours – charlietfl Nov 21 '18 at 00:50
3

With vanilla javascript:

x = []
for (i=1; i<=20; i=i+10) {
    y = []
    for (j=0; j<10; j++) {
        y.push(i + j)
    }
    x.push(y)
}
console.log(x)

For anyone who's interested, I time clocked these answers and this is the fastest. Using 1 million entries, this clocks at .100 seconds. Lodash chunk clocks close behind at .110s. Array.from lags behind at .254s.

Conner
  • 30,144
  • 8
  • 52
  • 73
3

Looking at the ES6 Array.from documentation you can see a range generator function:

const range = (start, stop, step) => Array.from({ length: (stop -
start) / step }, (_, i) => start + (i * step));

So with that in mind you could generate the range via:

range(1, 21, 1)  // account for the 0 with the 21 otherwise you get 1-19

Then all that is missing is the chunk function:

const range = (start, stop, step) => Array.from({ length: (stop - start) / step }, (_, i) => start + (i * step));
const chunkBy = (arr, by=2) => arr.reduce((r,c,i) => (i%by==0 ? r.push([c]) : r[r.length-1] = [...r[r.length-1], c], r), [])

console.log(chunkBy(range(1,21,1), 10))

The chunkBy uses Array.reduce & the % operator to chunk the data.

Akrion
  • 18,117
  • 1
  • 34
  • 54