【问题标题】:Ruby, equally distribute elements and interleave/merge multiple arraysRuby,平均分配元素并交错/合并多个数组
【发布时间】:2013-03-26 03:35:41
【问题描述】:

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

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]

我认为可以这样做

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

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 个元素,但可能最大的应该排在第一位。

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

【问题讨论】:

  • 你的问题真的没有意义。为什么是[nil, :a, nil, :c, nil, :e] 而不是[:a, :c, :e, nil, nil]
  • 因为需要在扩展数组中平均分配元素(以便元素之间的空间几乎相等)而不仅仅是扩展数组。

标签: ruby arrays merge distribute


【解决方案1】:

我会使用排序来做到这一点,基于元素索引位置,除以数组的大小,加上一些基于数组 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]

【讨论】:

  • 谢谢,我刚刚检查过,它确实有效。起初似乎有点复杂的解决方案,但实际上并非如此。我会等几天再接受让我们看看是否有人找到另一个解决方案:) 而且我不能使用随机播放,因为每次它随机分配元素并且顺序不再合乎逻辑。
  • 实际上似乎也适用于 def sort_pos array (1..array.size).map { |i| (i - 0.5)/array.size } 结束
  • 讨厌无法在 cmets 中正确显示代码。无论如何,我创建了 gist gist.github.com/davispuh/5246323 为什么是 id 魔术?没有它们似乎工作得很好:)
  • “id”实际上应该称为“offset”,只是为了提供对排序中的关系的控制。它可能是过度设计并且您不需要 - 如果您对 Ruby 的默认排序感到满意,您可以安全地删除 id 参数,我认为当每个项目有关联时应该保留原始顺序(例如,如果您添加两个 4 元素数组,您添加的第二个中的每个项目将直接出现在第一个中的每个项目之后)
猜你喜欢
  • 2017-01-31
  • 1970-01-01
  • 1970-01-01
  • 2011-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多