Ruby中的Array上的Each_Slice

时间:2014-10-07 23:06:41

标签: ruby arrays

我希望得到一个嵌套数组,其中包含至少包含三个元素但最多包含四个元素的单个数组。当我到达10时,我遇到了一个问题:

example = [1,2,3,4,5,6,7,8,9,10]

example.each_slice(3).to_a = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
example.each_slice(4).to_a = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]

期望的结果是:

[[1, 2, 3], [4, 5, 6], [7, 8, 9, 10]]       (all arrays have 3 elements but no more than 4)

each_slice不是这样做的吗?

由于

2 个答案:

答案 0 :(得分:2)

each_slice生成最大所需大小的切片;它不会直接完成你想要的东西,这是一种“平衡”的清单。幸运的是,我们可以到达那里。

list = (1..10).to_a
slice_count = (list.length / 3.0).floor
list.each_slice(slice_count).to_a.each {|l| l.fill nil, slice_count, 0 }.transpose.map(&:compact)
# => [[1, 4, 7, 10], [2, 5, 8], [3, 6, 9]]

这不保留排序,但它确实平衡了值。它的工作方式是它基本上创建一个值的矩阵,其中至少填充每列的前3行,第四列用于捕获溢出。

1  2  3
4  5  6
7  8  9
10 -  -

然后使用#transpose从列中创建数组,然后我们压缩以删除nils。

保留订单有点困难,并且需要一些if条件。在这种情况下,具有3/4元素的数组的所需分布将影响答案。

答案 1 :(得分:1)

这是你可以做到的一种方法,它保留了顺序,并最大化了包含三个元素的数组的数量,最后放置了零个,一个或两个四个数组。

<强>代码

def divide_up(arr)
  sz = arr.size
  return nil if [0,1,2,5].include?(sz)
  n3, d = sz.divmod(3)
  return arr.each_slice(3).to_a if d.zero?
  return arr.each_slice(4).to_a if d==n3
  n3 -= d
  arr[0,3*n3].each_slice(3).to_a + arr[3*n3..-1].each_slice(4).to_a
end

注意方法第五行中的d==n3(d==1 && n3==1) || (d==2 && n3==2)的简写。

<强>实施例

16.times do |n|
  arr = [*1..n]
  puts "for: #{arr}:"
  a=divide_up(arr)
  puts "  #{(a ? a : "No solution")}"
end
  #=> for: []:
  #     No solution
  #   for: [1]:
  #     No solution
  #   for: [1, 2]:
  #     No solution
  #   for: [1, 2, 3]:
  #     [[1, 2, 3]]
  #   for: [1, 2, 3, 4]:
  #     [[1, 2, 3, 4]]
  #   for: [1, 2, 3, 4, 5]:
  #     No solution
  #   for: [1, 2, 3, 4, 5, 6]:
  #     [[1, 2, 3], [4, 5, 6]]
  #   for: [1, 2, 3, 4, 5, 6, 7]:
  #     [[1, 2, 3], [4, 5, 6, 7]]
  #   for: [1, 2, 3, 4, 5, 6, 7, 8]:
  #     [[1, 2, 3, 4], [5, 6, 7, 8]]
  #   for: [1, 2, 3, 4, 5, 6, 7, 8, 9]:
  #     [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
  #   for: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:
  #     [[1, 2, 3], [4, 5, 6], [7, 8, 9, 10]]
  #   for: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]:
  #     [[1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]
  #   for: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]:
  #     [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
  #   for: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]:
  #     [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12, 13]]
  #   for: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]:
  #     [[1, 2, 3], [4, 5, 6], [7, 8, 9, 10], [11, 12, 13, 14]]
  #   for: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]:
  #     [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15]]