Ich versuche, eine Möglichkeit zu finden, die Existenz eines Werts in einem Array zu überprüfen, ohne das Array zu durchlaufen.
Ich lese eine Datei für einen Parameter. Ich habe eine lange Liste von Parametern, mit denen ich mich nicht befassen möchte. Ich habe diese unerwünschten Parameter in ein Array eingefügt @badparams
.
Ich möchte einen neuen Parameter lesen und wenn er in nicht vorhanden ist @badparams
, verarbeiten Sie ihn. Wenn es in vorhanden ist @badparams
, fahren Sie mit dem nächsten Lesevorgang fort.
perl
arrays
comparison
Mel
quelle
quelle
Antworten:
Verwandeln Sie das Array einfach in einen Hash:
Sie können der Liste auch weitere (eindeutige) Parameter hinzufügen:
Und später eine Liste mit (eindeutigen) Parametern zurückbekommen:
quelle
1
erneut festgelegt wird.Bester allgemeiner Zweck - Besonders kurze Arrays (1000 Elemente oder weniger) und Codierer, die sich nicht sicher sind, welche Optimierungen ihren Anforderungen am besten entsprechen.
Es wurde erwähnt, dass grep alle Werte durchläuft, auch wenn der erste Wert im Array übereinstimmt. Dies ist wahr, jedoch ist grep in den meisten Fällen immer noch extrem schnell . Wenn Sie über kurze Arrays (weniger als 1000 Elemente) sprechen, werden die meisten Algorithmen sowieso ziemlich schnell sein. Wenn Sie über sehr lange Arrays (1.000.000 Elemente) sprechen, ist grep akzeptabel schnell, unabhängig davon, ob das Element das erste oder das mittlere oder das letzte im Array ist.
Optimierungsfälle für längere Arrays:
Wenn Ihr Array sortiert ist , verwenden Sie eine "binäre Suche".
Wenn dasselbe Array mehrmals durchsucht wird, kopieren Sie es zuerst in einen Hash und überprüfen Sie dann den Hash. Wenn der Speicher ein Problem darstellt, verschieben Sie jedes Element aus dem Array in den Hash. Effizienter, zerstört jedoch das ursprüngliche Array.
Wenn dieselben Werte innerhalb des Arrays wiederholt gesucht werden , erstellen Sie träge einen Cache. (Wenn jedes Element durchsucht wird, überprüfen Sie zuerst, ob das Suchergebnis in einem persistierten Hash gespeichert wurde. Wenn das Suchergebnis nicht im Hash gefunden wird, durchsuchen Sie das Array und fügen Sie das Ergebnis in den persistierten Hash ein, damit wir es beim nächsten Mal tun finde es im Hash und überspringe die Suche).
Hinweis: Diese Optimierungen sind nur bei langen Arrays schneller. Nicht zu stark optimieren.
quelle
Sie können die Smartmatch-Funktion in Perl 5.10 wie folgt verwenden:
Für die Suche nach wörtlichen Werten reicht es aus, wenn Sie unten nachschlagen.
Für die skalare Suche funktioniert das Ausführen von unten wie oben.
Für Inline-Arrays, die unten ausgeführt werden, funktioniert dies wie oben.
In Perl 5.18 ist Smartmatch als experimentell gekennzeichnet. Daher müssen Sie die Warnungen deaktivieren, indem Sie das experimentelle Pragma aktivieren, indem Sie Folgendes zu Ihrem Skript / Modul hinzufügen:
Alternativ, wenn Sie die Verwendung von Smartmatch vermeiden möchten - dann, wie Aaron sagte, verwenden Sie:
quelle
use experimental 'smartmatch'
empfohlen wird. Da ich die Kontrolle über meine Perl-Version (internes System) habe, verwende ich dieno warnings 'experimental::smartmatch';
Anweisung.Dieser Blog-Beitrag beschreibt die besten Antworten auf diese Frage.
Kurz gesagt, wenn Sie CPAN-Module installieren können, sind die am besten lesbaren Lösungen:
oder
Eine häufigere Redewendung ist jedoch:
Aber bitte nutzen Sie die
first()
Funktion nicht! Es drückt überhaupt nicht die Absicht Ihres Codes aus. Verwenden Sie nicht den~~
Operator "Smart Match": Er ist defekt. Und verwenden Siegrep()
weder die Lösung noch einen Hash: Sie durchlaufen die gesamte Liste.any()
wird aufhören, sobald es Ihren Wert findet.Weitere Informationen finden Sie im Blog-Beitrag.
quelle
use List::Util qw(any);
.List::Util
ist in Kernmodulen .Methode 1: grep (kann vorsichtig sein, wenn erwartet wird, dass der Wert ein regulärer Ausdruck ist).
Vermeiden Sie die Verwendung
grep
, wenn Sie sich Ressourcen ansehen.Methode 2: Lineare Suche
Methode 3: Verwenden Sie einen Hash
Methode 4: Smartmatch
(hinzugefügt in Perl 5.10, markiert ist experimentell in Perl 5.18).
Methode 5: Verwenden Sie das Modul
List::MoreUtils
quelle
@ eakssjos Benchmark ist gebrochen - Maßnahmen zum Erstellen von Hashes in Schleifen im Vergleich zum Erstellen von regulären Ausdrücken in Schleifen. Feste Version (plus ich habe hinzugefügt
List::Util::first
undList::MoreUtils::any
):Und Ergebnis (es ist für 100_000 Iterationen, zehnmal mehr als in @ eakssjos Antwort):
quelle
Obwohl es bequem zu bedienen ist, scheint es, dass die Konvertierung in Hash-Lösung ziemlich viel Leistung kostet, was für mich ein Problem war.
Ausgabe des Benchmark-Tests:
quelle
List::Util::first
ist schneller, da die Iteration beendet wird, wenn eine Übereinstimmung gefunden wird.grep
ist erheblich langsamer als das Erstellen von Hashs und das Durchführen von Suchvorgängen, da erstere O (n) und letztere O (1) sind. Führen Sie die Hash-Erstellung nur einmal durch (außerhalb der Schleife) und berechnen Sie den regulären Ausdruck vorab, um nur Methoden zu messen ( siehe meine Antwort ).@files ist ein vorhandenes Array
/^2[\d‹.[\d‹[A-za-z‹?/ = vaues ab 2 hier können Sie jeden regulären Ausdruck setzen
quelle
Sie wollen hier sicher einen Hash. Platzieren Sie die fehlerhaften Parameter als Schlüssel im Hash und entscheiden Sie dann, ob ein bestimmter Parameter im Hash vorhanden ist.
Wenn Sie wirklich daran interessiert sind, dies mit einem Array zu tun, schauen Sie sich
List::Util
oder anList::MoreUtils
quelle
Es gibt zwei Möglichkeiten, dies zu tun. Sie können die Werte in einen Hash für eine Nachschlagetabelle werfen, wie in den anderen Beiträgen vorgeschlagen. (Ich werde nur eine weitere Redewendung hinzufügen.)
Wenn es sich jedoch um Daten handelt, die hauptsächlich aus Wortzeichen und nicht zu vielen Metas bestehen, können Sie sie in eine Regex-Abwechslung kopieren:
Diese Lösung müsste auf die Arten von "schlechten Werten" abgestimmt werden, nach denen Sie suchen. Und wieder, es könnte für bestimmte Arten von Saiten völlig ungeeignet sein, also Vorbehalt Emptor .
quelle
@bad_param_lookup{@bad_params} = ()
, aber Sie müssen verwendenexists
, um die Mitgliedschaft zu testen.Möglicherweise möchten Sie die Konsistenz numerischer führender Leerzeichen überprüfen
quelle