70

配列を、ほぼ同じサイズの小さい配列の正確な数に分割する方法が必要です。誰かがこれを行う方法がありますか?

例えば

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] 
groups = a.method_i_need(3)
groups.inspect
    => [[1,2,3,4,5], [6,7,8,9], [10,11,12,13]]

これは、配列をチャンクに分割することとはまったく別の問題であることに注意してください。これは、a.each_slice(3).to_a5つのグループ(私たちが望むように3つではない)を生成し、最終的なグループは他のグループとは完全に異なるサイズになる可能性があるためです。

[[1,2,3], [4,5,6], [7,8,9], [10,11,12], [13]]  # this is NOT desired here.

この問題では、必要なチャンクの数が事前に指定されており、各チャンクのサイズは最大で1だけ異なります。

4

5 に答える 5

131

あなたが探しています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]]
于 2012-09-11T17:12:03.400 に答える
122

他の回答がすでに受け入れられているため、質問を誤解している可能性がありますが、各グループのサイズに関係なく、配列を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]]

ルビーに相当するものはないと思いますが、次の簡単な方法を追加することで、ほぼ同じ結果を得ることができます。

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
于 2012-11-29T20:47:48.280 に答える
16

試す

a.in_groups_of(3,false)

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

于 2012-09-11T17:12:55.897 に答える
5

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]]
于 2017-03-10T14:47:38.853 に答える
3

これには、余分な部分を塗りつぶすためのより良い賢さが必要ですが、それは合理的なスタートです。

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]] 
于 2017-11-06T09:41:57.617 に答える