Wie kann ich einen zufälligen Wert aus einer Liste mit F # auswählen?

7

Ich bin neu in F # und ich versuche herauszufinden, wie man einen zufälligen String-Wert aus einer Liste / einem Array von Strings zurückgibt.

Ich habe eine Liste wie folgt:

%Vor%

Wie kann ich einen Gegenstand aus der obigen Liste zufällig auswählen und zurückgeben?

Hier ist mein erster Versuch:

%Vor%     
codet3str 23.10.2015, 22:22
quelle

3 Antworten

7

Ihr Problem besteht darin, dass Sie Array s und F # List s mischen ( *type*[] ist eine Typnotation für Array ). Sie könnten es ändern, um Listen zu verwenden:

%Vor%

Das heißt, die Indizierung in List ist normalerweise eine schlechte Idee, da sie eine O (n) -Leistung hat, da eine F # -Liste im Grunde eine Linked-List ist. Sie sollten besser combos in ein Array machen, wenn möglich wie folgt:

%Vor%     
mydogisbox 23.10.2015, 22:40
quelle
11

Beide Antworten von latkin und mydogisbox sind gut, aber ich möchte noch einen dritten Ansatz hinzufügen, den ich manchmal verwende. Dieser Ansatz ist nicht schneller, aber flexibler und kompostierbarer und schnell genug für kleine Sequenzen. Je nach Ihren Anforderungen können Sie eine der hier aufgeführten leistungsstärkeren Optionen verwenden, oder Sie können Folgendes verwenden.

Funktion mit einem Argument unter Verwendung von Random

Anstatt dir direkt die Auswahl eines einzelnen Elements zu erlauben, definiere ich oft eine Funktion shuffleR wie folgt:

%Vor%

Diese Funktion hat den Typ System.Random -> seq<'a> -> seq<'a> , also funktioniert sie mit jeder Art von Sequenz: Listen, Arrays, Sammlungen und lazy evaluierten Sequenzen (allerdings nicht mit unendlichen Sequenzen).

Wenn Sie ein einzelnes zufälliges Element aus einer Liste möchten, können Sie das immer noch tun:

%Vor%

Sie können aber auch sagen, drei zufällig ausgewählte Elemente:

%Vor%

Keine Argumentfunktion

Manchmal ist es mir egal, dass ich diesen Random Wert übergeben muss, also definiere ich diese alternative Version:

%Vor%

Es funktioniert auf die gleiche Weise:

%Vor%

Obwohl der Zweck von Guid.NewGuid() nicht darin besteht, Zufallszahlen zu liefern, ist es oft zufällig genug für meine Zwecke - zufällig, in dem Sinne, dass es unberechenbar ist.

Verallgemeinerte Funktion

Weder shuffleR noch shuffleG sind wirklich zufällig. Aufgrund der Funktionsweise von Random und Guid.NewGuid() können beide Funktionen zu leicht verzerrten Verteilungen führen. Wenn dies ein Problem ist, können Sie eine noch allgemeinere Funktion shuffle definieren:

%Vor%

Diese Funktion hat den Typ (unit -> 'a) -> seq<'b> -> seq<'b> when 'a : comparison . Es kann weiterhin mit Random verwendet werden:

%Vor%

Sie können es aber auch mit einigen kryptographisch sicheren Zufallszahlengeneratoren verwenden, die von der Basisklassenbibliothek bereitgestellt werden:

%Vor%

FSI:

%Vor%

Wie Sie aus diesem Code entnehmen können, ist es leider ziemlich umständlich und spröde. Sie müssen die Länge der Sequenz von vorne kennen; RNGCryptoServiceProvider implementiert IDisposable , also sollten Sie sicherstellen, dass rng nach der Verwendung gelöscht wird; und Elemente werden nach der Verwendung aus q entfernt, was bedeutet, dass sie nicht wiederverwendet werden können.

Kryptografisch zufällige Sortierung oder Auswahl

Wenn Sie wirklich eine kryptografisch korrekte Sortierung oder Auswahl benötigen, wäre es einfacher, dies so zu tun:

%Vor%

Verwendung:

%Vor%

Das war aber nie etwas, was ich jemals tun musste, aber ich dachte, ich würde es hier der Vollständigkeit halber hinzufügen. Während ich es nicht gemessen habe, ist es wahrscheinlich nicht die schnellste Implementierung, aber es sollte kryptographisch zufällig sein.

    
Mark Seemann 24.10.2015 08:27
quelle

Tags und Links