以n,m,o组或更多组分组数组

时间:2017-08-31 13:21:35

标签: arrays ruby split

有没有像这样拆分数组的方法?

[1, 2, 3, 4, 5, 6, 7, 8, 9].split(3, 4, 2)
#=> [[1, 2, 3],[4, 5, 6, 7],[8, 9]]

5 个答案:

答案 0 :(得分:2)

λ的不可变版本:

▶ splitter = ->(array, *parts) do 
    parts.reduce([[], 0]) do |acc, i|
      right = acc.last + i
      [acc.first << (acc.last...right), right]
    end.first.map { |r| array[r] }
  end
#⇒ #<Proc:0x0055ae3d9ae7c8@(pry):18 (lambda)>
▶ splitter.((1..9).to_a, 3, 4, 2)
#⇒ [[1, 2, 3], [4, 5, 6, 7], [8, 9]]

答案 1 :(得分:1)

不,没有,但你可以轻松自己写一个。

class Array
  def in_groups_of_n(*sizes)
   sizes.map(&method(:shift))
  end
end

实施例

arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
arr.in_groups_of_n(3, 4, 2)
# => [[1, 2, 3], [4, 5, 6, 7], [8, 9]]

Demonstration

如果您需要非破坏性版本,可以使用dup方法:

class Array
  def in_groups_of_n(*sizes)
   duplicate = dup
   sizes.map { |size| duplicate.shift(size) }
  end
end

arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
arr.in_groups_of_n(3,4,2)
# => [[1, 2, 3], [4, 5, 6, 7], [8, 9]
arr
# => [1, 2, 3, 4, 5, 6, 7, 8, 9]

Demonstration

答案 2 :(得分:1)

这是一个天真的数组实现:

class Array
  def multi_split(*sizes)
    r = []
    e = self.each
    sizes.each do |size|
      t = []
      size.times do
        t << e.next
      end
      r << t
    end
    r
  end
end

p [1, 2, 3, 4, 5, 6, 7, 8, 9].multi_split(3, 4, 2)
# [[1, 2, 3], [4, 5, 6, 7], [8, 9]]

@Stefan提到在Enumerable上实现它可能是有意义的:

module Enumerable
  def multi_split(*sizes)
    Enumerator.new do |yielder|
      e = self.each
      sizes.each do |size|
        yielder << Array.new(size){ e.next }
      end
    end
  end
end

p [1, 2, 3, 4, 5, 6, 7, 8, 9].multi_split(3, 4, 2).to_a
# [[1, 2, 3], [4, 5, 6, 7], [8, 9]]

答案 3 :(得分:1)

另一个选项(如果分割不等于数组大小

,则无损
def split_at(arr,splits)
  rest = arr.last(arr.size - splits.reduce(:+))
  enum = arr.to_enum
  splits.map do |n| 
    n.times.map { enum.next } 
  end.concat(rest.empty? ? [] : [rest])
end

然后称为

split_at (1..9), [3,4,2]
#=> [[1, 2, 3], [4, 5, 6, 7], [8, 9]]
split_at (1..22), [3,4,2]
#=> [[1, 2, 3], [4, 5, 6, 7], [8, 9], [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22]]

Example

答案 4 :(得分:1)

class Array
  def split_by_number(*sizes)
    sizes.each_with_object([]) { |n,a| a << [a.empty? ? 0 : a.last.sum, n] }.
          map { |start, nbr| self[start, nbr] }
  end
end

[1, 2, 3, 4, 5, 6, 7, 8, 9].split_by_number 3, 4, 2
  #=> [[1, 2, 3], [4, 5, 6, 7], [8, 9]]

请注意

[3, 4, 2].each_with_object([]) { |n,a| a << [a.empty? ? 0 : a.last.sum, n] }
  #=> [[0, 3], [3, 4], [7, 2]]