1

我正在使用针对 .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+FunctorComparer1[LinqBridge.Tuple`2[System.String,System.Int32]]'。

但它似乎在 .NET 4.0 中工作得很好。有解决方法吗?不幸的是,我在这种情况下坚持使用 .NET 2.0。

编辑使用最新版本的 LINQ Bridge (1.2)

4

1 回答 1

2

又一次更新

我发现这个问题和你有同样的问题: 为什么在排序中使用随机导致[无法排序 IComparer.Compare 错误]
问题是 LINQBridgeList<>.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 错误。 我建议更新到最新版本。 您看到此问题没有其他明显的原因。

附加信息

您可以使用 aRandom而不是Guid这样:

var rnd = new Random();
var result = someCollection.OrderBy(g => rnd.Next()).Take(1).FirstOrDefault();

此外,.Take(1)绝对没有必要紧随其后.FirstOrDefault()

于 2011-12-01T23:19:06.653 回答