最新消息: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 - Split array into different size chunks (4, 3, 3, 3, 4, 3, 3, 3, etc) - Stack Overflow

matteradmin10PV0评论

I have an array like so: [1, 2, 3, 4, 5, 6, 7, 9, 10]. I need to chunk it into different size chunks, yet with a simple pattern of: 4, 3, 3, 3, 4, 3, 3, 3 like so:

[
    [ // four
        1,
        2,
        3,
        4
    ],
    [ // three (1/3)
        5,
        6,
        7
    ],
    [ // three (2/3)
        8,
        9,
        10
    ],
    [ // three (3/3)
        11,
        12,
        13
    ],
    [ // four
        14,
        15,
        16,
        17
    ],
    [ // three (1/3)
        18,
        19,
        20
    ], // and so on..
]

I have tried with this code I have customized:

const arr; // my array of values
const chuncked = arr.reduce((acc, product, i) => {
    if (i % 3) {
        return acc;
    } else if (!didFourWayReduce) {
        didFourWayReduce = true;
        fourWayReduces++;

        if ((fourWayReduces - 1) % 2) { // only make every second a "4 row"
            return [...acc, arr.slice(i, i + 3)];
        } else {
            return [...acc, arr.slice(i, i + 4)];
        }
    } else {
        didFourWayReduce = false;
        return [...acc, arr.slice(i, i + 3)];
    }
}, []);

And it works, almost, expect that the first chunk of threes (1/3) have the last element of the chunk with 4. So 1 key is repeated every first chunk of three. Like so:

[
    [
        1,
        2,
        3,
        4
    ],
    [
        4, // this one is repeated, and it shouldn't be
        5,
        6
    ]
]

I have an array like so: [1, 2, 3, 4, 5, 6, 7, 9, 10]. I need to chunk it into different size chunks, yet with a simple pattern of: 4, 3, 3, 3, 4, 3, 3, 3 like so:

[
    [ // four
        1,
        2,
        3,
        4
    ],
    [ // three (1/3)
        5,
        6,
        7
    ],
    [ // three (2/3)
        8,
        9,
        10
    ],
    [ // three (3/3)
        11,
        12,
        13
    ],
    [ // four
        14,
        15,
        16,
        17
    ],
    [ // three (1/3)
        18,
        19,
        20
    ], // and so on..
]

I have tried with this code I have customized:

const arr; // my array of values
const chuncked = arr.reduce((acc, product, i) => {
    if (i % 3) {
        return acc;
    } else if (!didFourWayReduce) {
        didFourWayReduce = true;
        fourWayReduces++;

        if ((fourWayReduces - 1) % 2) { // only make every second a "4 row"
            return [...acc, arr.slice(i, i + 3)];
        } else {
            return [...acc, arr.slice(i, i + 4)];
        }
    } else {
        didFourWayReduce = false;
        return [...acc, arr.slice(i, i + 3)];
    }
}, []);

And it works, almost, expect that the first chunk of threes (1/3) have the last element of the chunk with 4. So 1 key is repeated every first chunk of three. Like so:

[
    [
        1,
        2,
        3,
        4
    ],
    [
        4, // this one is repeated, and it shouldn't be
        5,
        6
    ]
]
Share Improve this question asked Feb 14, 2020 at 18:33 FooBarFooBar 6,13811 gold badges52 silver badges105 bronze badges
Add a ment  | 

5 Answers 5

Reset to default 10

You could take two indices, one for the data array and one for sizes. Then slice the array with a given length and push the chunk to the chunks array.

Proceed until end of data.

var data = Array.from({ length: 26 }, (_, i) => i + 1),
    sizes = [4, 3, 3, 3],
    i = 0,
    j = 0,
    chunks = [];

while (i < data.length) chunks.push(data.slice(i, i += sizes[j++ % sizes.length]));

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

A recursive approach is fairly elegant:

const chunks = (xs, [s, ...ss]) =>
  xs.length ? [xs .slice (0, s), ... chunks (xs .slice (s), [...ss, s])] : []

const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
const sizes = [4, 3, 3, 3]

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

By replacing [s, ...ss] with [...ss, s], we pass a cycled version of the sizes array, so that for instance, [4, 3, 3, 3] bees [3, 3, 3, 4]. This makes it easy to parse step-by-step.

const arr = Array.from({ length: 100 }, (_, i) => i);

const copy = [...arr];

const sizes = [4, 3, 3, 3];

const result = [];

let i = 0;

while (i <= arr.length && copy.length) {
  result.push(copy.splice(0, sizes[i % sizes.length]));
  i++;
}

console.log(result);

Mod operator to check if it should be 4 or 3. Use two arrays just to make it easier (can be done with one)

const groupIt = arr => arr.reduce(({
  group,
  out
}, v, i) => {
  var max = out.length % 4 === 0 ? 4 : 3
  group.push(v)
  if (group.length === max || i === arr.length - 1) {
    out.push(group)
    group = []
  }
  return {
    group,
    out
  }
}, {
  group: [],
  out: []
}).out

console.log(groupIt([1, 2, 3, 4, 5, 6, 7, 8]))

var test = (new Array(30)).fill(0).map((x,i) => i + 1)
console.log(groupIt(test))

with just one:

const groupIt = arr => arr.reduce((out, v, i) => {
  var max = (out.length - 1) % 4 === 0 ? 4 : 3
  out[out.length - 1].push(v)
  if (out[out.length - 1].length === max) {
    out.push([])
  }
  return out
}, [[]])

console.log(groupIt([1, 2, 3, 4, 5, 6, 7, 8]))

var test = (new Array(30)).fill(0).map((x, i) => i + 1)
console.log(groupIt(test))

This answer is similar to that of Nina Scholz, but uses a for loop, which I personally find more clear.

const arr = Array.from({length: 100}, (_, i) => i + 1);
const sizes = [4, 3, 3, 3];
const result = [];

for (let i = 0, j = 0; i < arr.length; i += sizes[j], j = (j + 1) % sizes.length) {
  result.push(arr.slice(i, i + sizes[j]));
}

console.log(result);

Articles related to this article

Post a comment

comment list (0)

  1. No comments so far