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% 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:
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:
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.
Anstatt dir direkt die Auswahl eines einzelnen Elements zu erlauben, definiere ich oft eine Funktion shuffleR
wie folgt:
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% Manchmal ist es mir egal, dass ich diesen Random
Wert übergeben muss, also definiere ich diese alternative Version:
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.
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:
Diese Funktion hat den Typ (unit -> 'a) -> seq<'b> -> seq<'b> when 'a : comparison
. Es kann weiterhin mit Random
verwendet werden:
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.
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.
Ich habe vor einiger Zeit einen Blogbeitrag zu genau diesem Thema geschrieben:
3 Ansätze gibt es dort, mit der Diskussion der Leistung und Kompromisse von jedem.
Zusammenfassend:
%Vor%Bearbeiten: Ich möchte klarstellen, dass oben einige Möglichkeiten gezeigt sind, ein zufälliges Element aus einer Liste zu erhalten, vorausgesetzt, Sie müssen eine Liste verwenden. Wenn es mit dem Rest des Designs Ihres Programms übereinstimmt, ist es definitiv effizienter, ein zufälliges Element aus einem Array zu entnehmen.
Tags und Links f# random f#-interactive