我正试着把一个数组分成三组。我希望在开头有剩余的部分(在下面的示例中[1, 2]
)。
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
...
#=> [[1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]
有什么好方法可以做到这一点吗?
分割数组的通常方法是:
arr.each_slice(3)
# => [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11]]
这将在最后给出剩余的
[10, 11]
。我试着如下,认为each_slice
可能会接受一个否定的参数,并将其读作向后遍历数组。arr.each_slice(-3)
唉,没用。
最佳答案
尽管可以将数组反转三次,但有一种更有效的方法可以实现目标:
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
a = arr.dup # not to modify it inplace
[a.shift(a.size % 3)] + a.each_slice(3).to_a
#⇒ [[1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]
顺便说一句,
arr.each_slice(3)
返回的是枚举数,而不是您在问题中发布的数组。按照Cary Swoveland的建议,UPD或作废:
n = a.size % 3
[a[0...n]] + a[n..-1].each_slice(3).to_a
upd通过@sawa清除
dup
:[a.first(a.size % 3)] + a.drop(a.size % 3).each_slice(3).to_a
upd只是出于好奇(假设输入没有
dup
元素):([nil] * (3 - a.size % 3) + a).each_slice(3).to_a.tap do |a|
a.unshift(a.shift.compact!)
end
上面的代码可能安全地运行在原始数组上,它不会就地修改它。
upd2正如stefan在评论中指出的,如果数组可以被3整除,那么上面的任何一个都将产生一个初始空切片。所以,正确的解决方案(最快的,顺便说一句)应该是:
(arr.size % 3).zero? ? arr.each_slice(3).to_a : ANY_OF_THE_ABOVE