合并两组不均匀的项目

时间:2015-05-05 21:23:50

标签: distribution collate

我正在努力将一组项目分配到另一组,我正在寻找可以提供帮助的算法。

例如,A组有42个项目,B组有16个项目。我想将两个组混合在一起,以便B在A中相当均匀地分布。因此,合并后的组看起来像:{AA B AAA B AA B AA B AAA .....}当然,这很容易如果A是B的倍数,但我的需求通常不是这样。

3 个答案:

答案 0 :(得分:0)

您可以从另一组的项目之间获取一组中的项目数量开始:

float number_between = bigger_set.size() / smaller_set.size();

迭代越大的集合,从累加器中减去每个循环1(用number_between初始化),每当此累加器低于0时从较小的集合插入一个项目,并用{{1}刷新它}:

number_between

修改

更改为:

float accumulator = number_between;
foreach(item : bigger_set) {
  result.add(item);
  accumulator = accumulator - 1;
  if (accumulator < 0) {
      result.add(next from smaller_set);
      accumulator = accumulator + number_between;
  } 
} 

如果您想确保较大的列表同时开始和结束结果列表。

编辑2

请注意,使用浮点运算可能会引入舍入和下溢错误。

例如,如果您使用的是IEEE单精度(尾数为24位~7位十进制数字),并且较大的列表比较小的列表大10 ^ 7或更多,则行{{1}会下溢(你会得到一个完全由较大的集合而不是较小的集合产生的结果)。

此外,舍入可能会导致尝试在耗尽时从较小的列表中提取更多项目。

答案 1 :(得分:0)

1)你可以连接这两个组,并从组合组中进行简单的采样,例如通过改组元素并迭代混合的组合集。

2)如果您更顺序地按顺序进行,您可以从概率为size(A) / (size(A) + size(B))size(B) / (size(A) + size(B))的每个组中进行抽样,其中size(A)size(B)是当前的A组和B组中的元素数量尚未被采样。换句话说,如果U是来自Uniform(0,1)随机数生成器的绘制:

if U <= size(A) / (size(A) + size(B))
   randomly draw next observation from A
else
   randomly draw next observation from B

在这两种方法中,AB最终均匀分布在整个范围内,这是一个相当均匀的统计描述分布&#34;

您没有指定语言,所以这里是Ruby中两种方法的具体实现。我将设置的大小减半,以保持输出长度合理,显然,由于使用随机性,每次运行时都会产生不同的结果。

第一种方法:

a = ['A'] * 21
b = ['B'] * 8
c = (a + b).shuffle
puts c.join(',')
例如,

产生了以下输出:

A,A,A,A,A,B,A,A,A,A,A,B,B,B,A,B,A,A,A,A,A,A,A,A,A,B,B,A,B

第二种方法:

a = ['A'] * 21
b = ['B'] * 8
c = []    
while a.length > 0 || b.length > 0
  c << (rand <= (a.length / (a.length + b.length).to_f) ? a.shift : b.shift)
end    
puts c.join(',')
例如,

产生了以下输出:

A,A,B,A,A,A,B,B,A,A,A,A,A,A,A,B,B,B,A,A,A,B,A,A,A,B,A,A,A

答案 2 :(得分:0)

好吧,我一直在玩这个,并提出了一个适用于我的目的的解决方案。我基本上将较大的项目混合到较小的项目中并循环回来,直到我用完较大的项目。

For Each item In smallerList
  mergedList.add(smallerID)
Next

itemsRemaining = biggerList.Count

While itemsRemaining > 0
  index = 0

  For i = 1 To smallerList.Count
    If index >= mergedList.Count or itemsRemaining = 0 Then Continue While

    mergedList.Insert(index , largerID)
    index += 2 + loopCount
    itemsRemaining -= 1
  Next

  loopCount += 1
End While

然后我可以用两个列表中的实际项目替换ID。

因此,对于我的原始示例(第1组有42个项目,第2组有16个项目),我最终得到:

111 2 111 2 111 2 111 2 111 2 111 2 111 2 111 2 111 2 111 2 11 2 11 2 11 2 11 2 11 2 11 2

这有点前装,但就我的目的而言,这样做会很好。