Ruby“bucketize”一个数组

时间:2012-12-28 22:00:22

标签: ruby-on-rails ruby

假设我有以下数组:

a = (1..10).to_a

是否有一个内置的ruby(或rails)功能能够将阵列分成完全N个大致相等的部分,同时保持顺序?

我正在寻找类似的东西:

a.bucketize(3)
=> [[1,2,3,4],[5,6,7],[8,9,10]]
a.bucketize(5)
=> [[1,2],[3,4],[5,6],[7,8],[9,10]]

提示:each_slice不会这样做。

另外,我知道我可以自己编写此函数并打开Array类或Enumerable模块。

感谢。

3 个答案:

答案 0 :(得分:4)

我会这样做:

ary = (1..10).to_a

ary.each_slice((ary.length.to_f/3).ceil).to_a
=> [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]

ary.each_slice((ary.length.to_f/5).ceil).to_a
=> [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]

这并不完美,但确实很接近:

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

ary.each_slice((ary.length.to_f/2).ceil).to_a
=> [[1, 2, 3, 4, 5], [6, 7, 8, 9]]

ary.each_slice((ary.length.to_f/3).ceil).to_a
=> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

ary.each_slice((ary.length.to_f/4).ceil).to_a
=> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

答案 1 :(得分:2)

使用功能方法可以最好地解决这类任务。这是一个尾递归函数实现(除了在数组上有效累积的不可避免的<<之外):

class Array
  def bucketize(n, index = 0, acc = [])
    return acc if n <= 0 || size <= index
    n0 = ((size - index).to_f / n).ceil
    bucketize(n - 1, index + n0, acc << self[index, n0])
  end
end

(1..9).to_a.bucketize(3)
#=> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
(1..10).to_a.bucketize(3)
#=> [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
(1..11).to_a.bucketize(3)
#=> [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11]]

答案 2 :(得分:0)

这是我最终做的事情:

class Array
  def bucketize(n)
    return [] if (buckets = n.to_i) <= 0
    j = length / buckets.to_f
    result = each_with_index.chunk { |_, i| (i / j).floor }.map { |_, v| v.map(&:first) }
    result << [] until result.length == buckets
    result
  end
end

示例:

a = (1..10).to_a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a.bucketize(1)
=> [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]
a.bucketize(2)
=> [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]
a.bucketize(3)
=> [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
a.bucketize(4)
=> [[1, 2, 3], [4, 5], [6, 7, 8], [9, 10]]
...
a.bucketize(9)
=> [[1, 2], [3], [4], [5], [6], [7], [8], [9], [10]]
...
a.bucketize(11)
=> [[1], [2], [3], [4], [5], [6], [7], [8], [9], [10], []]