首先,我確實瞭解了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