Diar
Diar

Reputation: 133

lodash chunk from end of array

I have an array

const myArray = [1, 2, 2, 2, 3, 3, 3, 4, 4, 4];

that I want to split into smaller arrays. I am using lodash chunk to do it.

_.chunk(myArray, 3);

this will return

[1, 2, 2], [2, 3, 3], [3, 4, 4], [4]

but I would like it to return

[1], [2, 2, 2], [3, 3, 3], [4, 4, 4]

my solution was this

_.chain(myArray).reverse().chunk(3).reverse().value()

it reverses the array, splits it and then reverses it again. But is there a better way to do this? So chunk starts from the end and not the start.

Upvotes: 3

Views: 2811

Answers (3)

Ori Drori
Ori Drori

Reputation: 191986

Find the remainder, and if there's remainder, slice it from the left side, and combine it with the chunks of the rest of the array. If no remainder, chunk normally:

const myArray = [1, 21, 22, 23, 31, 32, 33, 41, 42, 43];

const chunkRight = (arr, size) => {
  const rm = arr.length % size;
  
  return rm ?
    [arr.slice(0, rm), ..._.chunk(arr.slice(rm), size)]
    :
    _.chunk(arr, size);
};

const result = chunkRight(myArray, 3);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

Upvotes: 4

Ele
Ele

Reputation: 33726

An alternative could be using the function reduceRight.

const myArray = [1, 2, 2, 2, 3, 3, 3, 4, 4, 4];
const chunks = myArray.reduceRight((a, n, i, arr) => {
  if (((arr.length - 1) - i) % a.chunk === 0) {
    a.current = [];
    a.chunks.unshift(a.current);
  }
  
  a.current.push(n);  
  return a;
}, {
  /*This is the size per chunk*/chunk: 3, 
  /*The array with the chunks*/ chunks: [], 
  /*The current array which is being filled*/ current: []}).chunks;

console.log(chunks);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 1

CertainPerformance
CertainPerformance

Reputation: 370789

There's no built-in argument option for that (or separate method like chunkEnd), but it's trivial to write something yourself that achieves the same thing without reverseing the array:

const chunkFromEnd = (arr, size) => {
  const firstSize = arr.length % size;
  const result = [arr.slice(0, firstSize)];
  
  for (let i = firstSize; i < arr.length; i += size) {
    result.push(arr.slice(i, i + size));
  }
  return result;
};
console.log(chunkFromEnd([1, 2, 2, 2, 3, 3, 3, 4, 4, 4], 3));
console.log(chunkFromEnd([1, 2, 2, 2, 3, 3, 3, 4, 9, 4, 4, 6, 2, 1], 3));

Upvotes: 1

Related Questions