首先,我确实了解了Fisher-Yates shuffle。但让我们说出于理由,我想让用户从下拉列表中选择一个排序选项。该列表将包括一个“随机”选项。根据他们的选择结果,我只想在IComparer实例中替换我的排序。 IComparer会是什么样子?使用IComparer随机播放
谷歌带来了有缺陷的结果,所有采取这种形式过多:
public class NaiveRandomizer<T> : IComparer<T>
{
private static Random rand = new Random();
public int Compare(T x, T y)
{
return (x.Equals(y))?0:rand.Next(-1, 2);
}
}
然而,实施有偏见,甚至会在某些情况下抛出异常。
void Test()
{
Console.WriteLine("NaiveRandomizer Test:");
var data = new List<int>() {1,2,3};
var sortCounts = new Dictionary<string, int>(6);
var randomly = new NaiveRandomizer<int>();
for (int i=0;i<10000;i++)
{ //always start with same list, in _the same order_.
var dataCopy = new List<int>(data);
dataCopy.Sort(randomly);
var key = WriteList(dataCopy);
if (sortCounts.ContainsKey(key))
sortCounts[key]++;
else
sortCounts.Add(key, 1);
}
foreach (KeyValuePair<string, int> item in sortCounts)
Console.WriteLine(item.Key + "\t" + item.Value);
}
string WriteList<T>(List<T> list)
{
string delim = "";
string result = "";
foreach(T item in list)
{
result += delim + item.ToString();
delim = ", ";
}
return result;
}
那么你怎么能实现随机IComparer<T>
上解决了这些问题:偏置可以用下面的代码来证明?它允许要求每个调用.Sort()
使用一个单独的IComparer实例,因为我没有看到任何其他方式做到这一点:项目必须使用一些其他的,真正的随机值进行比较,但该值必须也对于给定排序操作中的项目是一致的。
我有一个开始here,但它被张贴在仓促,是非常慢,甚至不返回所有可能的排序(测试表明,它确实至少消除偏差,如果不计算缺少选项)。我不希望像Fisher-Yates这样的O(n)表现,但我确实需要一些合理的东西(对于一个小型的n n来说),而且我希望它能展示所有可能的类型。不幸的是,该链接是目前公认的答案,因此我希望能够用一些更好的东西来替代它。
如果没有其他的东西,我希望这是所有那些寻找IComparable解决方案的谷歌查询的磁铁 - 他们最终会在这里而不是别的地方告诉他们使用不正确的版本。
你能解释为什么这个实现是偏颇或抛出一个异常? (为我自己的教化) – 2009-02-17 17:43:02
从我看到的例外是NullReferenceException。偏见......不知道。 – 2009-02-17 17:44:42
我会添加一些代码来证明偏见。 – 2009-02-17 17:49:06