如何在 Ruby 中将数组拆分为多个随机大小的小数组?

4
我在 Ruby 中有多个长度可变的数组,长度从 1 到 40 不等:
@items 是一个典型的数组,其长度可以从 1 到 40,例如:
@items = [1, 2, 3, 4, 5, 6]

我想随机将数组分成长度为1、2或3的小数组,得到如下结果(例如)。
@items = [[1, 2],[3],[4,5,6]]

或者

@items = [[1],[2, 3],[4],[5,6]]

等等

我知道你可以使用@items.each_slice(3)来拆分数组......其中3是固定长度。但是我想随机拆分长度不同的大型数组为大小为1、2或3的数组... 最好的方法是什么?

5个回答

7
items, @items = @items.dup, []
@items.push(items.shift(rand(1..3))) until items.empty?

不错。如果某人的 Ruby 版本早于 1.9.3,则 Kernel#rand 只接受一个 fixnum max,而不是一个范围。@items.push(items.shift(1+rand(3))) until items.empty? 可以在旧版本的 Ruby 中使用。 - dbenhur

3
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b = []
until a.empty?
  b << a.shift((1..a.size).to_a.sample)
end
# b => [[1, 2], [3, 4, 5, 6, 7], [8, 9], [10]]
# change everytime though

你可以通过将 a.size 替换为任何你想要的数值来限制子数组的大小,比如替换为 3


1

为了好玩,我想尝试使用纯函数形式解决这个问题,不使用任何可变方法:

( (0..@items.size)
    .inject([0]) { |m,_| m + [m.last + 1 + rand(3)] }
    .take_while  { |i| i < @items.size } + [@items.size] ).
  each_cons(2).
  map { |s,e| @items[s...e] }

1
这个解决方案可能使用了太多的本地变量,但它不会破坏输入数组,并且对于数组窗口的最大值非常灵活。
def rotateAndTake inputArray, windowSize
  rotator, returnArray, breaker = 0, [], true
  while breaker do
    window = rand(windowSize)+1
    if(rotator + window > inputArray.length) then
      window = inputArray.length - rotator
      breaker = false
    end
    returnArray << inputArray.rotate(rotator).take(window) if window > 0
    rotator += window
  end
  returnArray
end

此外,我只是想写一个使用“rotate”方法的解决方案。

0

这里是另一个函数式解决方案:

( [0]+
  (1..a.length-1)
    .to_a
    .sample(rand(a.length))
    .sort+
  [a.length]
).each_cons(2).map{|i,j| a[i..j-1]}

1
这可以生成长度大于3的子数组。a[i...j]是指 a[i..j-1] 的更友好方式。我认为它可能会有偏向更短的子数组。 - dbenhur

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接