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 %code% s und F # %code% s mischen ( %code% ist eine Typnotation für %code% ). Sie könnten es ändern, um Listen zu verwenden:
%Vor%Das heißt, die Indizierung in %code% 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 %code% in ein Array machen, wenn möglich wie folgt:
%Vor%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 %code% wie folgt:
%Vor%Diese Funktion hat den Typ %code% , 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 %code% Wert übergeben muss, also definiere ich diese alternative Version:
%Vor%Es funktioniert auf die gleiche Weise:
%Vor%Obwohl der Zweck von %code% 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 %code% noch %code% sind wirklich zufällig. Aufgrund der Funktionsweise von %code% und %code% können beide Funktionen zu leicht verzerrten Verteilungen führen. Wenn dies ein Problem ist, können Sie eine noch allgemeinere Funktion %code% definieren:
%Vor%Diese Funktion hat den Typ %code% . Es kann weiterhin mit %code% 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; %code% implementiert %code% , also sollten Sie sicherstellen, dass %code% nach der Verwendung gelöscht wird; und Elemente werden nach der Verwendung aus %code% 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.