Überprüfen Sie, ob in einem Array in Ruby ein Wert vorhanden ist
Ich habe einen Wert 'Dog'
und ein array ['Cat', 'Dog', 'Bird']
.
Wie kann ich überprüfen, ob es existiert in dem array ohne Schleife durchgehen? Gibt es eine einfache Möglichkeit zu überprüfen, ob der Wert vorhanden ist, nichts mehr?
InformationsquelleAutor der Frage user211662 | 2009-12-31
Du musst angemeldet sein, um einen Kommentar abzugeben.
Du suchst
?
:InformationsquelleAutor der Antwort Brian Campbell
Es ist ein
?
Methode inActiveSupport
(Teil-Schienen) seit v3.1, wie bereits von @campaterson. So innerhalb der Schienen, oder wenn Sierequire 'active_support'
können Sie schreiben:OTOH, es gibt keine
in
Betreiber oder#in?
Methode in Ruby selbst, obwohl es hat gewesen schlug vor, insbesondere durch Yusuke Endoh ein erstklassiges Mitglied von ruby-core.Als von anderen darauf hingewiesen wird, die reverse-Methode
?
vorhanden ist, für alleEnumerable
s einschließlichArray
Hash
Set
Range
:Beachten Sie, dass wenn Sie viele Werte im array, Sie werden alle geprüft, einer nach dem anderen (D. H.
O(n)
), während die, Suche für einen Hashwert konstanter Zeit (ich.eO(1)
). Wenn Sie also array ist Konstante, für Beispiel, es ist eine gute Idee, ein Set statt. E. g:Einen Schnelltest zeigt, dass der Aufruf
include?
auf eine 10-elementSet
ist etwa 3,5 x schneller als der Aufruf auf der entsprechendenArray
(wenn das element nicht gefunden).Einer endgültigen Schließung Hinweis: seien Sie vorsichtig bei der Verwendung von
include?
auf eineRange
gibt es Feinheiten, so finden Sie der doc und vergleichen Sie mitdecken?
...InformationsquelleAutor der Antwort Marc-André Lafortune
Versuchen
InformationsquelleAutor der Antwort schmitzelburger
Verwenden
Enumerable#include
:Oder, wenn eine Reihe von tests fertig sind,1 können Sie loszuwerden, die Schleife (die auch
include?
hat) und gehen von O(n) zu O(1) mit:1 ist. Ich hoffe, das ist offensichtlich, aber, den Kopf ab, Beanstandungen: ja, nur für ein paar lookups, die Hash[] und transponieren ops Dominieren das Profil und sind jeweils O(n) selbst.
InformationsquelleAutor der Antwort DigitalRoss
Wenn Sie prüfen wollen, durch einen block, könnten Sie versuchen, jede? oder alle?.
Details sind hier: http://ruby-doc.org/core-1.9.3/Enumerable.html
Meine inspiration kommt von hier: https://stackoverflow.com/a/10342734/576497
InformationsquelleAutor der Antwort Van
Mehrere Antworten deuten
Array#include?
aber es gibt eine wichtige Einschränkung: auf der Suche an der Quelle, auchArray#include?
hat ausführen von Schleifen:Dem Weg zum testen der word-Präsenz ohne looping ist die Erstellung einer trie für das array. Es gibt viele versuche Implementierungen gibt (google "ruby trie"). Ich werde
rambling-trie
in diesem Beispiel:Und jetzt sind wir bereit zu testen, die Anwesenheit der verschiedenen Wörter im array ohne Schleife über Sie, in
O(log n)
Zeit, mit gleichen syntaktischen Einfachheit alsArray#include?
mit sublinearTrie#include?
:InformationsquelleAutor der Antwort Boris Stitnicky
Ruby hat 11 Methoden zum finden von Elementen in einem array.
Bevorzugt ist
include?
Oder für den wiederholten Zugriff, das erstellen einer Reihe und rufen dann
include?
odermember?
Hier sind Sie alle,
Alle von Ihnen kehren ein
true
ish Wert, wenn das element vorhanden ist.include?
ist die bevorzugte Methode. Es verwendet eine C-Sprachefor
loop intern, die bricht, wenn ein element entspricht der internenrb_equal_opt/rb_equal
Funktionen. Ist es nicht viel effizienter, es sei denn, Sie erstellen Sie eine Gruppe für die wiederholte Mitgliedschaft überprüft.member?
wird nicht neu definiert, inArray
Klasse und verwendet eine nicht optimierte Umsetzung vonEnumerable
Modul, das buchstäblich Durchlaufen aller Elemente.Übersetzt, um Ruby-code, dieser sieht über die folgenden
Beide
include?
undmember?
habenO(n)
Zeit, Komplexität, da die beiden Suche im array nach dem ersten auftreten des erwarteten Wertes.Können wir ein set zu bekommen
O(1)
Zugriffszeit auf die Kosten haben, erstellen Sie eine hash-Repräsentation des Arrays zuerst. Wenn Sie wiederholt zu prüfen, die Mitgliedschaft auf den gleichen array, diese anfängliche Investitionen zahlen sich schnell aus.Set
ist nicht implementiert in C, aber als nur-Ruby-Klasse, noch dieO(1)
Zugriffszeit der zugrunde liegenden@hash
macht diese lohnt.Hier ist die Umsetzung der
Set
Klasse,Wie Sie sehen können die
Set
Klasse erzeugt nur eine interne@hash
Instanz, Karten, alle Objektetrue
und prüft dann die Mitgliedschaft mitHash#include?
umgesetzt wird mitO(1)
Zugriffszeit inHash
Klasse.Werde ich nicht diskutieren, die anderen 7 Methoden, wie Sie sind weniger effizient.
Gibt es eigentlich noch mehr Methoden mit
O(n)
Komplexität über die 11 oben aufgeführten, aber ich beschloss, nicht die Liste, da Sie Scannen das gesamte array anstatt zu brechen bei dem ersten Spiel.Nicht, verwenden Sie diese,
InformationsquelleAutor der Antwort akuhn
Wenn Sie nicht wollen, um die Schleife, es gibt keinen Weg, es zu tun mit Arrays. Sie sollten die Verwendung von einem Satz statt.
Setzt intern arbeiten wie hashes, damit Ruby nicht brauchen, um eine Schleife durch die Sammlung, um Elemente zu finden, da wie der name schon sagt, erzeugt Hashwerte von den keys und schafft eine Speicher-Zuordnung, so dass jeder hash point bis zu einer bestimmten Stelle im Speicher. Vorherigen Beispiel erfolgt mit einer Hash:
Der Nachteil ist, dass die Sets und hash-Schlüssel können nur enthalten einzigartige Gegenstände, und wenn Sie hinzufügen, eine Menge von Elementen, Ruby haben wird, um sofort wieder die ganze Sache nach einer bestimmten Anzahl von Elementen, um erstellen eine neue Karte, passt ein größerer Schlüsselraum. Weitere Informationen hierzu empfehle ich Ihnen die Uhr MountainWest RubyConf 2014 - Big O in einer Hausgemachten Hash von Nathan Long
Hier ist ein benchmark:
Und die Ergebnisse:
InformationsquelleAutor der Antwort Kimmo Lehto
Dies ist ein weiterer Weg, dies zu tun: verwenden Sie die Array#index-Methode.
Es gibt den index des ersten Auftretens des Elements in dem array.
Beispiel:
index() kann auch ein block
beispielsweise
hier, gib den index des ersten Wortes in dem array, das mit den Buchstaben 'o'.
InformationsquelleAutor der Antwort Zack Xu
Gibt es mehrere Möglichkeiten, dies zu erreichen. Ein paar von Ihnen sind wie folgt:
InformationsquelleAutor der Antwort sumit
Spaß Tatsache,
Können Sie
*
zu überprüfen, array-Mitgliedschaft in einemcase
Ausdrücken.Beachten Sie die etwas
*
in der when-Klausel, diese Prüfungen für die Mitgliedschaft in der array.Alle üblichen magic Verhalten der splat-operator gilt, so zum Beispiel, wenn
array
ist nicht wirklich ein array, aber ein einzelnes element es entspricht dem element.InformationsquelleAutor der Antwort akuhn
Dies wird dir nicht nur sagen, dass es existiert, sondern auch, wie oft es angezeigt wird:
InformationsquelleAutor der Antwort user3245240
Für was es Wert ist, Die Ruby-docs sind eine erstaunliche Ressource, die für diese Art von Fragen.
Ich würde auch beachten Sie die Länge des Arrays, die Sie suchen durch. Die
include?
Methode führt eine lineare Suche mit O(n) Komplexität, die kann ziemlich hässlich werden, je nach der Größe des Arrays.Wenn Sie arbeiten mit einer großen (sortierte) array, ich würde schreiben ein binäre Suche Algorithmus das sollte nicht allzu schwierig sein, und hat eine worst-case von O(log n).
Oder wenn Sie mit Ruby 2.0 ist, können Sie die Vorteile
bsearch
.InformationsquelleAutor der Antwort davissp14
Wenn du auf Geist mehr Werte... können Sie Folgendes versuchen:
Beispiel: wenn Katze und Hund vorhanden sind im array:
Statt:
Hinweis: - Mitglied? und? sind die gleichen.
Dies tun können, die Arbeit in einer Zeile!
InformationsquelleAutor der Antwort Daniel Antonio Nuñez Carhuayo
Gibt es das auch Umgekehrt!
Angenommen, der array [ :edit, :update, :create, :show ] - gut, vielleicht die gesamte seven deadly/restful Sünden 🙂
Sowie weitere Spielzeug mit der Idee der ziehen eine gültige Aktion von einigen string - sagen
Lösung
InformationsquelleAutor der Antwort walt_die
Wenn wir nicht benutzen willst
include?
dies funktioniert auch:InformationsquelleAutor der Antwort xlembouras
Konvertieren
arr
zuhash
überprüfen Sie nun in O(1) - multiples mal für jede Taste :hash = arr.map {|x| [x,true]}.to_h
Leistung Hash#has_key? versus Array#include?
InformationsquelleAutor der Antwort aqfaridi
Wie wäre es mit diesem Weg?
InformationsquelleAutor der Antwort ajahongir
InformationsquelleAutor der Antwort Rahul Patel
Versuchen mit einschließen? für ein array. Zum Beispiel Wenn Anweisung true zurückgibt, dann wird dieser Wert existiert in der Reihe, sonst nicht.
InformationsquelleAutor der Antwort Vitthal Bobade
wenn Sie nicht möchten, zu verwenden sind? Sie können zuerst wickeln Sie das element in ein array und überprüfen Sie, ob das umwickelte element ist gleich dem Schnittpunkt von array und element gewickelt. Dies wird geben einen booleschen Wert zurück, basierend auf Gleichheit.
InformationsquelleAutor der Antwort mgidea
Hier ist eine weitere Möglichkeit, um dies zu tun:
InformationsquelleAutor der Antwort Wand Maker
InformationsquelleAutor der Antwort Matthew Maurice
Finden Sie in Ihrem array:
['Cat', 'Dog', 'Bird'].include?('Dog')
oder
['Cat', 'Dog', 'Bird'].include? 'Dog'
InformationsquelleAutor der Antwort Uriel