SORU
17 AĞUSTOS 2009, PAZARTESİ


Rastgele ve OrderBy kullanarak iyi bir karıştırma algoritması?

Üzerinde çeşitli shuffle algoritmaları hakkında an article Coding Horror okudum. Bir yerlerde insanlar bir listeyi karıştırmak için bunu yapmış olduğunu gördüm:

var r = new Random();
var shuffled = ordered.OrderBy(x => r.Next());

Bu iyi bir karıştırma algoritması? Tam olarak nasıl çalışır? Bunu yapmanın uygun bir yolu mu?

CEVAP
17 AĞUSTOS 2009, PAZARTESİ


Değil bir şekilde ayaklarını sürüyor gibi, çoğunlukla üzerinde gerekçesiyle bu O(n log n) için iyi bir neden olduğunda kolay uygulamak bir O(n) Karıştır. Kod soru "" temelde bir rastgele (umarım eşsiz!) vererek çalışır her elemanın numarasını, sonra bu sayıya göre öğeleri sipariş.

Swap elemanları Fisher-Yates shuffle Durstenfield varyantı tercih ederim.

Shuffle uzantısı basit bir yöntem uygulamaya temelde giriş ToList ToArray sonra Fisher-Yates varolan bir uygulama kullanarak arama oluşacak. (Genellikle hayatı daha güzel yapmak için bir parametre olarak Random geçer.) Uygulamaları etrafında bir sürü vardır... belki bir cevap içinde bir yerde olacaktı.

Böyle bir uzatma yöntemi hakkında güzel bir şey o zaman gerçekten ne yapmak istediğini okuyucuya çok açık olurdu.

EDİT: basit bir uygulama geldi (hiçbir hata denetimi!):

public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng)
{
    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 = rng.Next(i   1);
        T tmp = elements[i];
        elements[i] = elements[swapIndex];
        elements[swapIndex] = tmp;
    }
    // Lazily yield (avoiding aliasing issues etc)
    foreach (T element in elements)
    {
        yield return element;
    }
}

EDİT: performans üzerinde aşağıya Yorum aslında biz onları karışık olarak: öğeleri iade edebiliriz hatırlattı

public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng)
{
    T[] elements = source.ToArray();
    for (int i = elements.Length - 1; i >= 0; i--)
    {
        // Swap element "i" with a random earlier element it (or itself)
        // ... except we don't really need to swap it fully, as we can
        // return it immediately, and afterwards it's irrelevant.
        int swapIndex = rng.Next(i   1);
        yield return elements[swapIndex];
        elements[swapIndex] = elements[i];
    }
}

Bu artık sadece ihtiyacı olduğu kadar iş yapar.

Her iki durumda da, Random örnek kullanım: hakkında dikkatli olmanız gerektiğini unutmayın

  • Hemen hemen aynı zamanda Random iki örneğini oluşturmak rasgele sayılar aynı sıra aynı şekilde kullanıldığında) verecektir
  • Random iş parçacığı için güvenli değil.

Bu konularda daha fazla detaya gider ve çözümler sağlayan an article on Random var.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Chip Johnson

    Chip Johnson

    30 AĞUSTOS 2007
  • Rootjunky.com

    Rootjunky.co

    22 EKİM 2011
  • Vsauce

    Vsauce

    30 Temmuz 2007