配列があるとしましょう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]]
それを行うための組み込み関数またはエレガントな方法はありますか?
配列があるとしましょう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]]
それを行うための組み込み関数またはエレガントな方法はありますか?
、を使用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]]
例のように値が連続している場合は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]]
私は以下のようにこれを行います:
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]]