【问题标题】:`Array#each_slice`, leaving remainders at the beginning`Array#each_slice`,在开头留下余数
【发布时间】:2016-04-08 23:18:37
【问题描述】:

我正在尝试将一个数组分成三组。我想把余数放在开头(在下面的例子中是[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)

唉,没用。

【问题讨论】:

    标签: arrays ruby multidimensional-array


    【解决方案1】:

    reverseeach_slice 的简单组合就可以解决问题:

    arr.reverse.each_slice(3).map(&:reverse).reverse
    #=> [[1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]
    

    说明:

    我正在反转数组并执行each_slice。那会给我:

    [[11, 10, 9], [8, 7, 6], [5, 4, 3], [2, 1]]
    

    现在我正在迭代这个并反转每个子数组以匹配预期的子数组序列与.map(&:reverse)。最后,我正在反转整个 Array 以获得所需的序列(最后一个 .reverse)。

    【讨论】:

    • 我正要发帖arr.reverse.each_slice(3).map{|a| a.reverse}.reverse。 :-D
    • 这读起来应该很快。您可以通过将第一个 reverse 替换为 reverse_each 来消除一个数组。
    • 感谢您 - 所有 cmets 都很棒。显然有很多方法可以给猫剥皮!只是想知道, map(&:reverse) 有点让我失望。那是什么的缩写形式吗?
    【解决方案2】:

    虽然可以将数组反转三次,但有更有效的方法来实现目标:

    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 的建议,取消 dup

    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 只是出于好奇(假设输入没有 nil 元素):

    ([nil] * (3 - a.size % 3) + a).each_slice(3).to_a.tap do |a|
      a.unshift(a.shift.compact!)
    end
    

    以上内容可以安全地在原始数组上运行,它不会就地修改它。

    UPD2 正如 Stefan 在 cmets 中指出的那样,如果数组可被 3 整除,上述任何操作都将产生一个初始空切片。因此,正确的解决方案(并且,最快的,顺便说一句)应该是这样的:

    (arr.size % 3).zero? ? arr.each_slice(3).to_a : ANY_OF_THE_ABOVE
    

    【讨论】:

    • 好答案。避免dupn = a.size(3); a[0,n] + a[n..-1].slice(3)
    • 如果你使用first(n)drop(n),那么你不必dup
    • 如果数组可以被 3 整除,所有这些都将产生一个初始的空切片,例如[[], [1, 2, 3], [4, 5, 6]
    猜你喜欢
    • 2011-08-31
    • 1970-01-01
    • 1970-01-01
    • 2011-08-24
    • 2019-08-24
    • 1970-01-01
    • 2017-11-10
    • 2021-04-04
    • 1970-01-01
    相关资源
    最近更新 更多