我正在使用针对.NET 2.0 Framework的LINQ Bridge,我收到以下错误。只想要随机选择的集合中的第一个元素。不关心这种特殊情况下的表现。
var result = someCollection.OrderBy(g => Guid.NewGuid()).Take(1).FirstOrDefault();
someCollection是List<string>
。集合中的值是唯一的。
无法排序,因为IComparer.Compare()方法返回 结果不一致。要么值不等于自身, 或者与另一个值重复比较的一个值产生不同 结果。 x:'',x的类型:'元组
2', IComparer: 'System.Array+FunctorComparer
1 [LinqBridge.Tuple`2 [System.String,System.Int32]]'。
但它似乎在.NET 4.0中运行得很好。这有解决方法吗?不幸的是,我坚持使用.NET 2.0来实现这种情况。
编辑使用最新版本的LINQ Bridge(1.2)
答案 0 :(得分:2)
我发现这个问题与您有同样的问题:
Why does using Random in Sort causing [Unable to sort IComparer.Compare error]
问题是LINQBridge在内部使用List<>.Sort
,当使用“不稳定”比较算法时会抱怨,所以遗憾的是你无法以这种方式随机化。
作为替代方案,这里有一些很棒的代码可以随机化或选择一个随机项目:
private static Random rnd = new Random();
/// <summary>
/// Chooses one of the items at random.
///
/// Returns default if there are no items.
/// </summary>
public static T RandomOrDefault<T>(this IEnumerable<T> source)
{
// We need the count:
var buffer = source as ICollection<T> ?? source.ToList(); // (iterate only once)
var itemCount = buffer.Count;
if (itemCount == 0)
{
return default(T);
}
var index = rnd.Next(itemCount);
return buffer.ElementAt(index);
}
/// <summary>
/// Randomizes the order of the elements of a sequence.
/// </summary>
public static IEnumerable<T> Randomize<T>(this IEnumerable<T> source)
{
// This code is an implementation of the Fisher–Yates shuffle.
// The code was obtained from:
// https://stackoverflow.com/questions/1287567/c-is-using-random-and-orderby-a-good-shuffle-algorithm/1665080#1665080
T[] elements = source.ToArray();
// Note i > 0 to avoid final pointless iteration
for (int i = elements.Length - 1; i > 0; i--)
{
// Swap element "i" with a random earlier element it (or itself)
int swapIndex = rnd.Next(i + 1);
yield return elements[swapIndex];
elements[swapIndex] = elements[i];
// we don't actually perform the swap; we can forget about the
// swapped element because we already returned it.
}
// there is one item remaining that was not returned - we return it now
yield return elements[0];
}
此异常看起来像LINQBridge错误。 我建议更新到最新版本。没有其他明显的理由让你看到这个问题。
您可以使用Random
代替Guid
,如下所示:
var rnd = new Random();
var result = someCollection.OrderBy(g => rnd.Next()).Take(1).FirstOrDefault();
此外,.Take(1)
.FirstOrDefault()
完全没必要