DEV Community

Cover image for Me vs AI: Splitting an array into rows of alternating length
Andreas Riedmüller
Andreas Riedmüller

Posted on • Updated on

Me vs AI: Splitting an array into rows of alternating length

I just had to split up an array of items into chunks with alternating one and two elements.

Here are two versions, the first one is written by me, the second one was generated by GitHub Copilot.

My own version

What I like most is that this is the very first time I've had to define more than one variable in a for statement!

It should also work for more complex scenarios.

const items = [0,0,0,0,0,0];
const rows = [];

for (let i = 0, countThisRow; i < items.length; i += countThisRow) {

  // Change this according to your needs
  if (rows.length % 2 === 0) {
    countThisRow = 1;
  } else {
    countThisRow = 2;
  }

  rows.push(items.slice(i, i + countThisRow));
}

console.log(rows);

// Result:
// [
//   [0],
//   [0, 0],
//   [0],
//   [0, 0]
// ]
Enter fullscreen mode Exit fullscreen mode

The AI version

While I was coding, Copilot failed to help me with this. Later I promted the chat and this is the version that was generated. Surprisingly it does not even work, I really thought that this is exactly something that Copilot is good for.

And even if I did correct it, it's a pain to read, isn't it?

If you find a prompt that works better let me know!

Prompt

I have to split up an array of many items into chunks with alternating one and two elements. Like from [0,0,0,0,0,0] to [0],[0,0],[0],[0,0]

Response

Sure! Here's an example function that takes an array and returns a new array with alternating chunks of one and two elements:

function alternateChunks(arr: any[]): any[] {
  const result = [];
  let i = 0;
  while (i < arr.length) {
    if (i === arr.length - 1) {
      result.push([arr[i]]);
      break;
    }
    result.push(arr.slice(i, i + 2));
    i += 2;
    if (i === arr.length - 1) {
      result.push([arr[i]]);
      break;
    }
  }
  return result;
}
Enter fullscreen mode Exit fullscreen mode

You can call this function with your array of items as an argument to get a new array with alternating chunks. For example, alternateChunks([0, 0, 0, 0, 0, 0]) would return [[0], [0, 0], [0], [0, 0]].

Your are lying Copilot 😜

Result of AI generated function

Top comments (6)

Collapse
 
artxe2 profile image
Yeom suyun

I do not trust AI code.
However, AI can sometimes be helpful for simple brainstorming.
For example, after asking AI to implement a piece of code, I might see that the code uses arr.slice, and that might spark an idea for the correct implementation.
Additionally, judging by the thumbnail image of the article, the initial value of countThisRow might need to be 1.
Finally, here is my own implementation of the given problem.

function solution(items) {
  const answer = []
  let i = 0
  let j = 0
  let length = items.length
  while (i + 2 < length) {
    answer[j++] = [items[i++]]
    answer[j++] = [items[i++], items[i++]]
  }
  if (i < length) answer[j++] = [items[i++]]
  if (i < length) answer[j++] = [items[i++]]
  return answer
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
merri profile image
Vesa Piittinen

Many ways to the same result.

function solution(items) {
    const answer = [];
    for (let i = 0, j = 0; i < items.length; i += j + 1, j = 1 - j) {
        answer.push(items.slice(i, i + j + 1));
    }
    return answer;
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
receter profile image
Andreas Riedmüller • Edited

It took me some time to understand it to be honest, nice approach. I like the j = 1 - j to switch between 0 and 1, I never thought of that, very clever. Thanks for your comment!

Thread Thread
 
merri profile image
Vesa Piittinen

I had a bored moment so I made it configurable:

function solution(items, ...sizes) {
    sizes = sizes.map((size) => Math.round(size)).filter((size) => size > 0);
    if (!sizes[0]) sizes = [1, 2];
    const answer = [];
    for (let i = 0, j = 0; i < items.length; i += sizes[j], j = (j + 1) % sizes.length) {
        answer.push(items.slice(i, i + sizes[j]));
    }
    return answer;
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
receter profile image
Andreas Riedmüller

You are 100% right, I really enjoy working with GitHub Copilot and I use it all the time. Like you said it often sparks and idea or gives really helpful hints. I was just really surprised that this prompt didn't work better.

Thanks for sharing your solution. What I really like about it is that the "template" of how the array is built is visible in line 7 and 8.

You could filter out undefined and empts rows and it gets very easy to change the template like so:

// 3 / 1 / 2 / …
function solution(items) {
  const answer = []
  let i = 0
  let j = 0
  let length = items.length
  while (i < length) {
    answer[j++] = [items[i++], items[i++], items[i++]]
    answer[j++] = [items[i++]]
    answer[j++] = [items[i++], items[i++]]
  }
  return answer.map(i => i.filter(j => typeof j !== 'undefined')).filter(i => i.length > 0);
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
receter profile image
Andreas Riedmüller • Edited

Additionally, judging by the thumbnail image of the article, the initial value of countThisRow might need to be 1.

You are right 😅

I have adapted it, thanks!