2

I have array like this:

[{i: 0, abc: true}, {i: 1, abc: true}, {i: 2, abc: true}, {i: 3, abc: true}, {i: 4, abc: true}, {i: 5, abc: true}, {i: 6, abc: true}, {i: 7, abc: true}, {i: 8, abc: true}, {i: 9, abc: true}, {i: 10, abc: true}, {i: 11, abc: true}, ]

I need to chunk it too have on output something like this:

[[{i: 0, abc: true}, {i: 1, abc: true}, {i: 2, abc: true}], [{i: 3, abc: true}, {i: 4, abc: true}, {i: 5, abc: true}], [{i: 5, abc: true}, {i: 6, abc: true}, {i: 7, abc: true}], [{i: 7, abc: true}, {i: 8, abc: true}, {i: 9, abc: true}], [{i: 9, abc: true}, {i: 10, abc: true}, {i: 11, abc: true}] ]

Last object in sub array is same as first object in next sub array.

Currently I write something like this :

const chunk = (arr, size) => Array.from( { length: Math.ceil(arr.length / size) }, (v, i) =>
arr.slice(i * size, i * size + size));

but it's only chunking by a specific number of elements. I can also achieve my goal by strange nested loops.. but maybe somebody knows better.. simpler way?

4
  • this one's easier - stackoverflow.com/questions/8495687/split-array-into-chunks Commented Apr 30, 2020 at 20:57
  • do search for answers before taking time to post your question. most common scenarios, such as the one you are asking for, are already solved in many programming languages. do close your question, unless you want something different than the one i have mentioned above. Commented Apr 30, 2020 at 20:59
  • Eh... really ... if I could find the answer to my question I wouldn't ask. Believe me :3 Commented Apr 30, 2020 at 21:03
  • fair enough. i find the approach in the link i shared to be more clearer. i would recommend that. Commented Apr 30, 2020 at 21:05

2 Answers 2

1

You can remove 1 from the slice start and end if the current chunk index (i) is not 0. However, since we're moving the index backwards by 1, we might have more chunks. We need to compare the number of total chunks with the decremented index, and without, and add to the number of pages accordingly.

const chunkMinus1 = (arr, size) => {
  const chunks = Math.ceil(arr.length / size)
  const maxItems = chunks * (size - 1) + 1
  const length = chunks + Math.ceil(Math.max(arr.length - maxItems, 0) / size)
  
  return Array.from(
    { length }, 
    (v, i) => arr.slice(i * size - (i ? 1 : 0), i * size + size - (i ? 1 : 0))
  )
};

const arr = [{i: 0, abc: true}, {i: 1, abc: true}, {i: 2, abc: true}, {i: 3, abc: true}, {i: 4, abc: true}, {i: 5, abc: true}, {i: 6, abc: true}, {i: 7, abc: true}, {i: 8, abc: true}, {i: 9, abc: true}, {i: 10, abc: true}, {i: 11, abc: true}]

const result = chunkMinus1(arr, 6)

console.log(result)

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. Your answer is not exactly what I want, but I improved it and now I have exactly what I needed.. const chunk = (arr, size) => Array.from( { length: Math.ceil(arr.length / size) }, (v, i) => arr.slice(i * size, i * size + size + 1 ) );
@tomcio61 - I've updated the answer to account for missing items, when the number of chunks doesn't cover all items because of the reduction in the index.
1

Here is a very simple way how to do it.

Introduce a new array every nth element (for your case every third) by using the modulo, find that nth element and add the elements to the last sub-array.

Fiddle proof: https://jsfiddle.net/2pzcLv9k/

   const result = input.reduce((acc, x, i) => {
   if (i % 3 === 0) {
     acc.push([x])
   } else {
     acc[acc.length - 1].push(x)
   }
   return acc;
 }, [])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.