2009-01-06 5 views

Répondre

12

Que diriez-vous d'une sorte de Knuth-Fisher-Yates shuffle algorithm?

for (int i = cards.Length - 1; i > 0; i--) 
{ 
    int n = rand.Next(i + 1); 
    Swap(ref cards[i], ref cards[n]); 
} 

Code tiré de Coding Horror. C'est aussi une lecture recommandée sur la façon dont les gens font souvent ce mal.

+0

Code de format comme code Mais bon algorithme – recursive

+0

@recursive Merci, je reformate le code – Gant

1

Ma solution préférée pour mélanger des choses est d'utiliser un tri N * log N et de lui transmettre un prédicat de tri qui retourne un résultat aléatoire. Il a la fonctionnalité intéressante qui peut être fait avec un minimum de nouveau code en utilisant des blocs de construction que la plupart des langues ont à portée de main, même dans les versions les plus rayées.

+0

Sur la D'autre part, un shuffle est seulement O (n) et est seulement environ 5 lignes de code, comme indiqué dans les autres réponses. (Et peut être fait une seule fois avec des génériques très facilement.) –

+0

5 lignes à 1 ligne est soit pas beaucoup (seulement 4 lignes) ou beaucoup (80%). Aussi, c'est plus simple à retenir. – BCS

+0

Et l'autre avantage est que le type pourrait tirer parti de quelque chose pour obtenir une bonne perf sur les swaps, donc pour un petit n, il pourrait être plus rapide. – BCS

2

Vous pouvez utiliser l'algorithme Fisher-Yates shuffle qui s'exécute en temps linéaire.

+0

Produit des résultats incorrects - voir http://www.codinghorror.com/blog/archives/001015.html –

+0

@LFSR: relire l'article? – Jimmy

+0

Qu'en est-il de Knuth? :( – configurator

0

Je voudrais créez une nouvelle liste et remplissez-la avec des éléments qui sont sélectionnés au hasard et supprimés de la liste originale.

6

Vérifiez cette façon Linq fraîche de le faire:

public class Employee 
{ 
    public int Id 
    { 
     get; 
     set; 
    } 
    public string Name 
    { 
     get; 
     set; 
    } 
} 

POPULATE une liste:

List<Employee> list = new List<Employee>(); 

    list.Add(new Employee { Id = 1, Name = "Davolio Nancy" }); 
    list.Add(new Employee { Id = 2, Name = "Fuller Andrew" }); 
    list.Add(new Employee { Id = 3, Name = "Leverling Janet" }); 
    list.Add(new Employee { Id = 4, Name = "Peacock Margaret" }); 
    list.Add(new Employee { Id = 5, Name = "Buchanan Steven" }); 
    list.Add(new Employee { Id = 6, Name = "Suyama Michael" }); 
    list.Add(new Employee { Id = 7, Name = "King Robert" }); 
    list.Add(new Employee { Id = 8, Name = "Callahan Laura" }); 
    list.Add(new Employee { Id = 9, Name = "Dodsworth Anne" }); 

Puis tri:

list = list.OrderBy(emp => Guid.NewGuid()).ToList(); 

Credit

+0

Pas exactement rapide, mais friggen génial. – Will

+0

Qui se soucie de la performance quand vous pouvez sortir votre gros bâton LINQ et montrer aux autres que vous êtes meilleur qu'eux? :-P – BFree

+0

Rappelez-vous que les GUID ne sont ** PAS ** à traiter comme des nombres aléatoires à des fins de chiffrement. Ils vont travailler pour ce genre de chose, mais ils ne sont pas interchangeables. –

0

Essayez cette co de here

Il utilise le IComparer.Compare

Ce sera une bonne pratique si vous faites la fonction à l'aide generics

Questions connexes