web-dev-qa-db-ja.com

rubyで配列を等しい部分に分割する

配列を同じサイズの別の配列内の一連の配列に分割する方法が必要です。誰でもこれを行う方法はありますか?

例えば

a = [0, 1, 2, 3, 4, 5, 6, 7]
a.method_i_need(3)
a.inspect
    => [[0,1,2], [3,4,5], [6,7]]
54
Red

あなたが探しています - Enumerable#each_slice

a = [0, 1, 2, 3, 4, 5, 6, 7]
a.each_slice(3) # => #<Enumerator: [0, 1, 2, 3, 4, 5, 6, 7]:each_slice(3)>
a.each_slice(3).to_a # => [[0, 1, 2], [3, 4, 5], [6, 7]]
108
Joshua Cheek

他の回答がすでに受け入れられているため、おそらく私は質問を誤解していますが、配列を3つのN個のグループに分割するのではなく、各グループのサイズに関係なく、配列を3つの等しいグループに分割したいようです以前の答えはありません。それがあなたが探しているものであれば、Rails(ActiveSupport)には in_groups というメソッドもあります:

a = [0,1,2,3,4,5,6]
a.in_groups(2) # => [[0,1,2,3],[4,5,6,nil]]
a.in_groups(3, false) # => [[0,1,2],[3,4], [5,6]]

Rubyに相当するものはありませんが、この簡単なメソッドを追加することでほぼ同じ結果を得ることができます。

class Array; def in_groups(num_groups)
  return [] if num_groups == 0
  slice_size = (self.size/Float(num_groups)).ceil
  groups = self.each_slice(slice_size).to_a
end; end

a.in_groups(3) # => [[0,1,2], [3,4,5], [6]]

ご覧のとおり、唯一の違いは、すべてのグループに「空のスペース」が広がることはありません。最後のグループを除くすべてのグループのサイズは等しく、最後のグループは常に残りとすべての「空のスペース」を保持します。

更新:@rimskyが先ほど指摘したように、上記の方法では常に正しい数のグループが得られるとは限りません(複数の「空のグループ」が作成されることがあります最後に、それらを除外します)。 ActiveSupportの定義 から切り取った更新バージョンは次のとおりです。これは、要求された数のグループを満たすためにエクストラを広げます。

def in_groups(number)
  group_size = size / number
  leftovers = size % number

  groups = []
  start = 0
  number.times do |index|
    length = group_size + (leftovers > 0 && leftovers > index ? 1 : 0)
    groups << slice(start, length)
    start += length
  end

  groups
end
100
mltsy

試して

a.in_groups_of(3,false)

それはあなたの仕事をします

16
Paritosh Singh

Mltsyが書いたように、in_groups(n, false)が仕事をするはずです。

正しいバランスmy_array.in_group(my_array.size.quo(max_size).ceil, false)を得るための小さなトリックを追加したかっただけです。

以下に、そのトリックを説明する例を示します。

a = (0..8).to_a
a.in_groups(4, false) => [[0, 1, 2], [3, 4], [5, 6], [7, 8]]
a.in_groups(a.size.quo(4).ceil, false) => [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
2
Maxime Brehin

これには、余分な断片を塗りつぶすために、より優れた賢さが必要ですが、それは合理的な出発点です。

def i_need(bits, r)
  c = r.count
  (1..bits - 1).map { |i| r.shift((c + i) * 1.0 / bits ) } + [r]
end

>   i_need(2, [1, 3, 5, 7, 2, 4, 6, 8])
 => [[1, 3, 5, 7], [2, 4, 6, 8]] 
> i_need(3, [1, 3, 5, 7, 2, 4, 6, 8])
 => [[1, 3, 5], [7, 2, 4], [6, 8]] 
> i_need(5, [1, 3, 5, 7, 2, 4, 6, 8])
 => [[1, 3], [5, 7], [2, 4], [6], [8]] 
1
android.weasel