-1

我有多个元素计数未知的数组,例如

a = []
a << [:a, :c, :e]
a << [:b, :f, :g, :h, :i, :j]
a << [:d]

结果应该类似于〜(由于四舍五入等,我真的不在乎细节)

r = [:b, :a, :f, :g, :d, :c, :h, :i, :e, :j]

这就是我认为可以做到的方式

首先,我们需要将每个数组中的元素平均扩展/分布相同的长度,所以我们得到类似

a << [nil, :a, nil, :c, nil, :e]
a << [:b, :f, :g, :h, :i, :j]
a << [nil, nil, :d, nil, nil]

接下来我们像往常一样交错它们

r = a.shift
a.each { |e| r = r.zip(e) }
r = r.flatten.compact

我目前的问题是如何在数组中平均(尽可能地)分布这些元素?可能有一个包含 4 个元素的数组,另一个包含 5 个元素,但可能最大的应该排在第一位。

当然很高兴看看是否有其他方法可以实现这一点:)

4

1 回答 1

2

我会使用一种排序来做到这一点,基于元素索引位置,除以数组的大小,加上一些基于数组 id 的偏移量,以保持一致(如果你不需要一致性,你可以使用一个小的随机偏移量来代替)。

a = [:a,:b]
b = [:c]
c = [:d,:e,:f]
d = [:g:,:h,:i,:j]

def sort_pos array, id
  (1..array.size).map { |i| (i - 0.5 + id/1000.0)/(array.size + 1e-6) }
end

# Combine all the arrays with their sort index, assigning ids to each array for consistency.
# Depending on how you receive these arrays, this structure can be built up programatically, 
# as long as you add an array plus its sort index numbers at the same time
combined = (a + b + c + d).zip( sort_pos(a, 1) +  sort_pos(b, 2) +  sort_pos(c, 3) +  sort_pos(d, 4) )


# Extract the values from the original arrays in their new order
combined.sort_by { |zipped| zipped[1] }.map { |zipped| zipped[0] }

=> [:g, :d, :a, :h, :e, :i, :b, :f, :j, :c]

在 Ruby 中可能有一种更简洁的方法来执行此操作。. . 但我认为最终结果是您所追求的 - 多个数组的“均匀”混合。

如果您只从统计角度关心混合的均匀性(即随着时间的推移它是“公平的”),您可以这样做:

(a+b+c+d).shuffle

=> [:g, :b, :i, :c, :a, :h, :e, :j, :f, :d]
于 2013-03-26T14:08:39.387 回答