-1

假设我有一个数组arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

如何拆分此数组以获取具有按步骤指定的元素的组?

例如:

input = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
...
output = [[1, 4, 7, 10], [2, 5, 8], [3, 6, 9]]

是否有任何内置功能或优雅的方式来做到这一点?

4

3 回答 3

4

使用Enumerable#each_slice, Array#zip

尝试以下操作:

input = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
n = 3
x = input.each_slice(n).to_a # => [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
output = x[0].zip(*x[1..-1]).map(&:compact) # => [[1, 4, 7, 10], [2, 5, 8], [3, 6, 9]]

不幸的是,你不能Array#transpose在这里使用:

>> input.each_slice(3).to_a.transpose
IndexError: element size differs (1 should be 3)
        from (irb):15:in `transpose'
        from (irb):15
        from C:/Ruby200-x64/bin/irb:12:in `<main>'

更新:替代

input = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
n = 3
output = (1..n).map { [] }
input.each_with_index do |x, i| output[i % n] << x end
output # => [[1, 4, 7, 10], [2, 5, 8], [3, 6, 9]]
于 2013-09-14T15:10:43.950 回答
2

如果这些值像您的示例一样是连续的,则可以group_by与您的步骤结合使用作为模数:

> (1..10).group_by {|v| v % 3 }.values
=> [[1, 4, 7, 10], [2, 5, 8], [3, 6, 9]] 

如果它们不是连续的,那么您仍然可以在单行中执行它,尽管它不那么优雅:

> (1..10).each_with_index.group_by {|v| v[1] % 3 }.map {|k,v| v.map &:first }
=> [[1, 4, 7, 10], [2, 5, 8], [3, 6, 9]] 
于 2013-09-14T17:26:22.533 回答
1

我会这样做如下:

n = 3
input = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a = input.each_slice(n).to_a
output = (0...n).map { |i| a.map{|e| e[i]}.compact }
# => [[1, 4, 7, 10], [2, 5, 8], [3, 6, 9]]

@falsetru的链接中以一种方法表示:

def divide(input, n)
  a = input.each_slice(n).to_a
  (0...n).map { |i| a.map{|e| e[i]}.compact }
end

p divide([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3)
p divide([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], 3)
p divide([1, 2, 3], 3)
# >> [[1, 4, 7, 10], [2, 5, 8], [3, 6, 9]]
# >> [[1, 4, 7, 10, 13, 16], [2, 5, 8, 11, 14], [3, 6, 9, 12, 15]]
# >> [[1], [2], [3]]
于 2013-09-14T16:56:11.903 回答