Подтвердить что ты не робот

Разделение массива на равные части в рубине

Мне нужен способ разбить массив на кучу массивов в другом массиве равного размера. У кого-нибудь есть способ сделать это?

Например

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

Ответ 1

Вы ищете 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]]

Ответ 2

Возможно, я неправильно понимаю вопрос, так как другой ответ уже принят, но это звучало так, будто вы хотели разделить массив на 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]]

Единственная разница (как вы можете видеть) заключается в том, что это не будет распространять "пустое пространство" во всех группах; каждая группа, но последняя равна по размеру, а последняя группа всегда содержит остаток плюс все "пустое пространство".

Update: Как отметил @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

Ответ 3

Try

a.in_groups_of(3,false)

Он выполнит вашу работу

Ответ 4

Как писал 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]]

Ответ 5

Для этого нужно немного умнее вымачивать лишние кусочки, но это разумное начало.

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]]