3

I wonder what is the idiom which used in lodash for reshaping arrays?

Basically, I'm looking for something that transforms this array : [1, 2, 3, 4, 5, 6, ,7, 8] to this one (in this case we've grouped each 3, but let's assume we are grouping each N) [[1, 2, 3], [4, 5, 6], [7, 8]]

I no pretty well how this should be done in pure js, but all my attempts to rewrite it in lodash are well, less readable after all.

shabunc
  • 23,119
  • 19
  • 77
  • 102
  • possible duplicate of [Split javascript array in chunks using underscore.js](http://stackoverflow.com/questions/8566667/split-javascript-array-in-chunks-using-underscore-js) – Bergi Oct 04 '13 at 12:30
  • I think this is a [pure JS task](http://stackoverflow.com/questions/8495687/split-array-into-chunks), any use of lodash methods will make it considerably slower. If you want to use it within the library, [`.mixin()`](http://lodash.com/docs#mixin) the pure implementation. – Bergi Oct 04 '13 at 12:33
  • 1
    @Bergi, well, while I agree with both of your assumptions - yes, it is better to be a pure js and yes, it is considerably slower, I've just wanted to find out, nevertheless, how it can be done. – shabunc Oct 04 '13 at 14:20

4 Answers4

7

A simple solution:

function reshape(array, n){
    return _.compact(array.map(function(el, i){
        if (i % n === 0) {
            return array.slice(i, i + n);
        }
    }))
}

A simple recursive solution:

function reshape(array, n) {
    if (array.length === 0)
        return [];
    return [_.take(array, n)].concat(reshape(_.rest(array, n), n));
}
Denis
  • 5,061
  • 1
  • 20
  • 22
  • I can imagine that you expect a pure one-liner in lodash, but I can't come up with one. I can come up with a pure js one-liner using `reduce`, but that's cheating. – Denis Oct 04 '13 at 10:32
  • Thank you! This is very close to what I'm finally came up to, but I've hoped that this is just because I'm not a hardcore lodash user ) – shabunc Oct 04 '13 at 10:49
  • 1
    I've added a much more efficient solution, but one that only uses `_.compact` from lodash. – Denis Oct 04 '13 at 10:58
  • Beware that, as of lodash 3.0, _.first() only returns the first element of the array and that _.take() must be used if you with to specify the number of elements from the beginning of the array to return. See https://lodash.com/docs#take and https://lodash.com/docs#first – Kabb5 Mar 13 '15 at 15:56
5

A bit late but as an extra example you can use zip.

For example:

.zip.apply(, _.chunk("Your array", "columns"));

How this works:

Let's say you have an array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, etc]

_.chunk(array, 3) will give you [ [1,2,3], [4,5,6], [7,8,9], [10,11,12], [13, 14] ]

.zip.apply(, _.chunk(array, 3)); will give you: [ [1,4,7,10,13], [2,5,8,11,14], [3,6,9,12] ]

https://lodash.com/docs#chunk

https://lodash.com/docs#zip

CronbachAlpha
  • 355
  • 1
  • 5
  • 14
1

You can also use _.transform:

function reshape (array, n) {
    return _.transform(array, function (result, el, i, arr) {
        return i % n === 0 ? result.push(arr.slice(i, i + n)) : null;
    });
}
s9k
  • 31
  • 2
1

I believe that you can do it this way, in a shorter version without even using lodash.

const chunk = (a, n) => [...Array(Math.ceil(a.length / n))].map((_, i)=> a.slice(n * i, n + n * i));

const arr = [1, 2, 3, 4, 5, 6, 7, 8];

const result = chunk(arr, 3);
console.log(result)
Nicolae Maties
  • 2,476
  • 1
  • 16
  • 26