最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

javascript - lodash chunk from end of array - Stack Overflow

matteradmin6PV0评论

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.

Runnable example:

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

console.log(_.chunk(myArray, 3));
  // => [1, 2, 2], [2, 3, 3], [3, 4, 4], [4]

console.log(_.chain(myArray).reverse().chunk(3).reverse().value());
  // => [1], [2, 2, 2], [3, 3, 3], [4, 4, 4]
<script src=".js/4.17.11/lodash.js"></script>

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.

Runnable example:

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

console.log(_.chunk(myArray, 3));
  // => [1, 2, 2], [2, 3, 3], [3, 4, 4], [4]

console.log(_.chain(myArray).reverse().chunk(3).reverse().value());
  // => [1], [2, 2, 2], [3, 3, 3], [4, 4, 4]
<script src="https://cdnjs.cloudflare./ajax/libs/lodash.js/4.17.11/lodash.js"></script>

Share Improve this question edited Feb 15 at 2:46 ggorlen 58.1k8 gold badges115 silver badges157 bronze badges asked Mar 8, 2019 at 0:12 DiarDiar 1432 silver badges9 bronze badges 3
  • Your reverse will probably also reverse the order of the items in each sub-array. You might not be seeing it because they're all the same value but you should probably check with more diverse data – Phil Commented Mar 8, 2019 at 0:17
  • Does the solution have to use Lodash or is vanilla JS also appropriate? – Phil Commented Mar 8, 2019 at 0:24
  • @Phil Hey. You're right. Now when I tested it with more diverse data it reverses the sub-arrays. The solution needs to use lodash but vanilla js is fine as long its not too much code. – Diar Commented Mar 8, 2019 at 0:30
Add a ment  | 

3 Answers 3

Reset to default 4

Find the remainder, and if there's remainder, slice it from the left side, and bine 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./ajax/libs/lodash.js/4.17.11/lodash.js"></script>

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));

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; }

Post a comment

comment list (0)

  1. No comments so far