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+FunctorComparerTuple 1[LinqBridge.Tuple`2[System.String,System.Int32]]'.

しかし、.NET 4.0 では問題なく動作するようです。これに対する回避策はありますか? 残念ながら、私はこのシナリオで .NET 2.0 を使用することに行き詰まっています。

編集LINQ Bridge (1.2) の最新バージョンを使用する

4

1 に答える 1

2

さらに別のアップデート

私はあなたと同じ問題を抱えているこの質問を見つけました: なぜソートでランダムを 使用すると[ IComparer.Compareエラーを並べ替えることができません]このようにランダム化することはできません。
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に代わりにa を使用できます。Guid

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

また、.Take(1)続く場合は一切不要です.FirstOrDefault()

于 2011-12-01T23:19:06.653 に答える