加权列表以使索引较低的项目更有可能被随机选择?

时间:2018-12-03 00:27:26

标签: c# random

我收到的List<Fruit>大小未知,通常介于4到10之间:

{ Apples, Orange, Pear, ?, ?, ... }  

如何以使List被选择的机会最高的方式对Apples进行加权,然后依次选择OrangePear

效果从本质上应该与从List中挑选一个随机物品是一样的:

{ Apples, Apples, Apples, Apples, Orange, Orange, Pear }

如果List的大小是固定的,我会做的

  1. 生成介于0.0-1.0之间的浮点数;
  2. 如果< 0.4,则返回Apples。否则,如果< 0.75返回Orange

请注意,此问题不是关于selecting a random item from a weighted list而是要对现有的任意长度的List进行加权,以这种方式进行随机拣选将导致项目被拣选的概率与其在项目中的位置成正比。 List

1 个答案:

答案 0 :(得分:2)

var weightedItems = myList
    .Select((item, index)
        => new { Item = item, Weight = 1f / Math.Pow(2, index) });

这将为您提供IEnumerable元组的ItemWeight的{​​{1}}增大时变小的Item。即:

index

您显然可以根据自己的喜好调整Item = Apples, Weight = 1 Item = Orange, Weight = 0.5 Item = Pear , Weight = 0.25 部分(用于计算重量)。我所使用的那个具有很好的副作用,即产生1f / Math.Pow(2, index),这是一个可以预测的范围,并使每个项目被拾取的可能性是前一个项目的一半。

可以根据您的要求从此结构中选择一个随机项目,如下所示:

  • 生成1到0之间的随机数
  • 从最低到最高1 >= n > 0迭代IEnumerable
  • 返回第一项Weight