スプラで待機している最中に考えてた。
その時は自分含めて5人いて、2人と3人にチーム分けしたかったのだが、それをRubyの1ライナーでやりたい。どうしようか
5人をAさん〜Eさんとする。ここまでは共通だと思う。
%w(Aさん Bさん Cさん Dさん Eさん).shuffle
方法1 group_byを使う
irb(main):016:0> %w(Aさん Bさん Cさん Dさん Eさん).shuffle.group_by.with_index{|a,i| i % 2 == 0} => {true=>["Aさん", "Bさん", "Eさん"], false=>["Dさん", "Cさん"]}
こっちのgroup_byはRailsの方ではなく組み込みの方。with_indexでindexが取れるのでその値が偶数か奇数かで2分割する。シンプルではあるが、2分割にしかできないのがキズ
group_by
の代わりにpartition
でも可
irb(main):037:0> %w(Aさん Bさん Cさん Dさん Eさん).shuffle.partition.with_index{|a,i| i % 2 == 0} => [["Cさん", "Dさん", "Eさん"], ["Bさん", "Aさん"]]
方法2 in_groupsを使う
これはRailsのメソッドだが、配列をn分割してくれるメソッド。しゅごい
[14] pry(main)> %w(Aさん Bさん Cさん Dさん Eさん).shuffle.in_groups(2) => [["Bさん", "Cさん", "Eさん"], ["Aさん", "Dさん", nil]]
これなら仮に人数増えて分割する数を増やしたいってなっても対応できる(8人なら4x4で分ければええやんってのはナシで
[16] pry(main)> %w(Aさん Bさん Cさん Dさん Eさん Fさん Gさん Hさん).shuffle.in_groups(3) => [["Cさん", "Eさん", "Aさん"], ["Bさん", "Fさん", "Dさん"], ["Hさん", "Gさん", nil]]
失敗例1 each_slice
これでも一応できる。しかし、引数に配列の長さ/2を明示的に渡さないといけないので。。。
irb(main):031:0> %w(Aさん Bさん Cさん Dさん Eさん).shuffle.each_slice(3).to_a => [["Bさん", "Dさん", "Eさん"], ["Aさん", "Cさん"]]