将数组拆分为不同大小的块(4、3、3、3、4、3、3、3 等)
Posted
技术标签:
【中文标题】将数组拆分为不同大小的块(4、3、3、3、4、3、3、3 等)【英文标题】:Split array into different size chunks (4, 3, 3, 3, 4, 3, 3, 3, etc) 【发布时间】:2020-05-30 13:49:43 【问题描述】:我有一个这样的数组:[1, 2, 3, 4, 5, 6, 7, 9, 10]
。我需要将它分成不同大小的块,但使用一个简单的模式: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..
]
我已经尝试使用我自定义的这段代码:
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)];
, []);
并且它几乎可以工作,期望第一个三块(1/3)具有该块的最后一个元素为 4。因此,每三个的第一个块重复 1 个键。像这样:
[
[
1,
2,
3,
4
],
[
4, // this one is repeated, and it shouldn't be
5,
6
]
]
【问题讨论】:
【参考方案1】:您可以使用两个索引,一个用于数据数组,一个用于大小。然后以给定长度对数组进行切片并将块推送到块数组。
继续直到数据结束。
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;
【讨论】:
太美了。可以对其进行调整,使其适用于无限长的数组吗?我看到你定义了固定的长度和尺寸。 如果sizes
和 j
的模式已经可以工作,余数为 sizes
的长度。
爱你的技能尼娜。难以置信你做的这么短!!【参考方案2】:
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);
【讨论】:
【参考方案3】:递归方法相当优雅:
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;
通过将[s, ...ss]
替换为[...ss, s]
,我们传递了sizes 数组的循环版本,例如,[4, 3, 3, 3]
变为[3, 3, 3, 4]
。这使得逐步解析变得容易。
【讨论】:
@NinaScholz:是的,没有人说这是高性能的,只有优雅。我们当然可以编写一个仅适用于索引的类似版本,但它可能不那么诱人。 例如const chunks = (xs, ss, i = 0, j = 0) => i < xs.length ? [xs .slice (i, i + ss[j]), ... chunks (xs, ss, i + ss[j], (j + 1) % ss.length)] : []
【参考方案4】:
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))
只有一个:
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))
【讨论】:
【参考方案5】:这个答案和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);
【讨论】:
以上是关于将数组拆分为不同大小的块(4、3、3、3、4、3、3、3 等)的主要内容,如果未能解决你的问题,请参考以下文章