-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_sliceArray#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 に答える