简体   繁体   English

将数组拆分为不同大小的块(4、3、3、3、4、3、3、3 等)

[英]Split array into different size chunks (4, 3, 3, 3, 4, 3, 3, 3, etc)

I have an array like so: [1, 2, 3, 4, 5, 6, 7, 9, 10] .我有一个这样的数组: [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:我需要将它分成不同大小的块,但使用简单的模式:4、3、3、3、4、3、3、3,如下所示:

[
    [ // 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.它几乎可以工作,期望第一个三元组 (1/3) 的最后一个元素为 4。因此,每个三元组的第一个块重复 1 个键。 Like so:像这样:

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

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

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

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] becomes [3, 3, 3, 4] .通过将[s, ...ss]替换为[...ss, s] ,我们传递了大小数组的循环版本,例如, [4, 3, 3, 3]变为[3, 3, 3, 4] This makes it easy to parse step-by-step.这使得逐步解析变得容易。

Mod operator to check if it should be 4 or 3. Use two arrays just to make it easier (can be done with one) Mod 运算符来检查它是否应该是 4 或 3。使用两个数组只是为了更容易(可以用一个来完成)

 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.这个答案类似于Nina Scholz 的答案,但使用了一个for循环,我个人觉得它更清楚。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM