Andrew: Ich rufe eine API auf und im JSON bekomme ich zurück, wenn es mehrere Ergebnisse gibt, bekomme ich ein Array, aber wenn es nur eines gibt, bekomme ich einen Hash anstatt eines einzelnen Element-Arrays. Gibt es einen besseren Forward als die Array vs Hash-Prüfung?
Drhyde
2
Also bekommst du entweder [result_hash, another_result_hash]oder single_result_hash? Wer auch immer diese API erstellt hat, hat keine gute Arbeit geleistet!
Andrew Grimm
2
Sie haben Recht, Andrew, und ich wette, es ist viel einfacher, die Leute, die die API geschrieben haben, dazu zu bringen, sie zu reparieren, als auf einen Hash im Vergleich zu einem Array zu testen.
Olivier 'Ölbaum' Scherler
Ich habe die gleiche Situation wie @drhyde. In meinem Fall ist der Drittanbieter HTTParty, der nach dem Parsen einer XML-Datei nicht entscheiden kann, wie am besten mit einer Situation umgegangen werden kann, in der ein Element 1-n Kinder haben kann.
Es ist erwähnenswert, dass das "is_a?" Die Methode ist wahr, wenn sich die Klasse an einer beliebigen Stelle im Stammbaum der Objekte befindet. zum Beispiel:
@some_var.is_a?(Object)# => true
Dies gilt, wenn @some_var eine Instanz eines Hashs oder einer anderen Klasse ist, die von Object stammt. Wenn Sie also eine strikte Übereinstimmung mit dem Klassentyp wünschen, verwenden Sie == oder instance_of? Methode ist wahrscheinlich das, wonach Sie suchen.
is_a?ist die beste Option, da sie auch truefür Unterklassen zurückgegeben wird.
Fábio Batista
Und natürlich lässt du auch die Klammern weg, @som_var.is_a? Hashfunktioniert also auch :)
Gus Shortz
7
Seien Sie vorsichtig, dies könnte Sie wirklich verarschen, wenn Ihnen jemand eine Instanz von ActiveSupport :: HashWithIndifferentAccess übergibt. Was wie ein Hash reagiert, aber eigentlich kein Hash ist. :(
Unflores
Ich hätte mir auch mehr detaillierte Antworten zum Thema Ententypisierung gewünscht, da der ursprüngliche Autor anscheinend nach einer rubinroten Methode zur Typprüfung suchte.
NobodysNightmare
3
@unflores ActiveSupport::HashWithIndifferentAccesserbt von Hash und gibt daher @some_var.is_a?(Hash)auch in diesem Fall true zurück. (Ich hatte gerade die gleiche Frage und HashWithIndifferentAccess-Fall und wurde ein wenig verwirrt von Ihrem Kommentar ... also wollte ich klarstellen)
Stilzk1n
38
Zuallererst ist die beste Antwort auf die wörtliche Frage
Hash===@some_var
Aber die Frage hätte wirklich beantwortet werden müssen, indem gezeigt wurde, wie man hier Enten tippt. Das hängt ein bisschen davon ab, welche Art von Ente du brauchst.
Normalerweise wollen Sie in Ruby, wenn Sie nach "Typ" suchen, tatsächlich den "Ententyp" oder "Ist Quacksalber wie eine Ente?". Sie würden sehen, ob es auf eine bestimmte Methode reagiert:
@some_var.respond_to?(:each)
Sie können über @some_var iterieren, da es auf Folgendes reagiert:
Wenn Sie den Typ wirklich kennen möchten und es sich um Hash oder Array handelt, können Sie Folgendes tun:
["Hash","Array"].include?(@some_var.class)#=> check both through instance class@some_var.kind_of?(Hash)#=> to check each at once@some_var.is_a?(Array)#=> same as kind_of
Dies funktioniert nicht, wenn Ihr Code von der Reihenfolge der Daten abhängt (z. B. wenn Sie each_with_index verwenden). Die Reihenfolge der Elemente ist unterschiedlich zwischen Hashes und Arrays implementiert , und es ist unterschiedlich zwischen rubin Versionen (. Intertwingly.net/slides/2008/oscon/ruby19/22 )
juan2raid
1
@ juan2raid: Wenn die Reihenfolge wichtig ist, rufen Sie sortsie zuerst an.
Andrew Grimm
@Brandon zweites Beispiel sollte die Klasse in Zeichenfolge konvertieren. <br/>["Hash", "Array"].include?(@some_var.class.to_s) #=> check both through instance class
OBCENEIKON
12
Hash===@some_var#=> return Boolean
Dies kann auch mit case-Anweisungen verwendet werden
In der Praxis möchten Sie häufig anders handeln, je nachdem, ob eine Variable ein Array oder ein Hash ist, und nicht nur sagen. In dieser Situation ist eine elegante Redewendung die folgende:
case item
whenArray#do somethingwhenHash#do something elseend
Beachten Sie, dass Sie die .classMethode nicht aufrufen item.
Beachten Sie, dass dies für Unterklassen nicht funktioniert ! Wenn Sie beispielsweise ein ActiveRecord::Collectionund versuchen, instance_of?(Array)wird dieses zurückgegeben false, während es zurückgegeben is_a?(Array)wird true.
Tom Lord
0
Wenn Sie testen möchten, ob ein Objekt streng ist oder a erweitert Hash, verwenden Sie:
value ={}
value.is_a?(Hash)|| value.is_a?(Array)#=> true
Aber um Rubys Enten-Tippen wertzuschätzen, könnten Sie Folgendes tun:
value ={}
value.respond_to?(:[])#=> true
Dies ist nützlich, wenn Sie nur über die value[:key]Syntax auf einen bestimmten Wert zugreifen möchten .
Bitte beachten Sie, dass Array.new["key"]a TypeError.
[result_hash, another_result_hash]
odersingle_result_hash
? Wer auch immer diese API erstellt hat, hat keine gute Arbeit geleistet!Antworten:
Sie können einfach tun:
oder auch so etwas wie:
Es ist erwähnenswert, dass das "is_a?" Die Methode ist wahr, wenn sich die Klasse an einer beliebigen Stelle im Stammbaum der Objekte befindet. zum Beispiel:
Dies gilt, wenn @some_var eine Instanz eines Hashs oder einer anderen Klasse ist, die von Object stammt. Wenn Sie also eine strikte Übereinstimmung mit dem Klassentyp wünschen, verwenden Sie == oder instance_of? Methode ist wahrscheinlich das, wonach Sie suchen.
quelle
is_a?
ist die beste Option, da sie auchtrue
für Unterklassen zurückgegeben wird.@som_var.is_a? Hash
funktioniert also auch :)ActiveSupport::HashWithIndifferentAccess
erbt von Hash und gibt daher@some_var.is_a?(Hash)
auch in diesem Fall true zurück. (Ich hatte gerade die gleiche Frage und HashWithIndifferentAccess-Fall und wurde ein wenig verwirrt von Ihrem Kommentar ... also wollte ich klarstellen)Zuallererst ist die beste Antwort auf die wörtliche Frage
Aber die Frage hätte wirklich beantwortet werden müssen, indem gezeigt wurde, wie man hier Enten tippt. Das hängt ein bisschen davon ab, welche Art von Ente du brauchst.
oder
oder auch
kann je nach Anwendung richtig sein.
quelle
Normalerweise wollen Sie in Ruby, wenn Sie nach "Typ" suchen, tatsächlich den "Ententyp" oder "Ist Quacksalber wie eine Ente?". Sie würden sehen, ob es auf eine bestimmte Methode reagiert:
Sie können über @some_var iterieren, da es auf Folgendes reagiert:
Wenn Sie den Typ wirklich kennen möchten und es sich um Hash oder Array handelt, können Sie Folgendes tun:
quelle
sort
sie zuerst an.["Hash", "Array"].include?(@some_var.class.to_s) #=> check both through instance class
Dies kann auch mit case-Anweisungen verwendet werden
quelle
Ich benutze das:
Es funktioniert für Hash und ActiveSupport :: HashWithIndifferentAccess.
quelle
In der Praxis möchten Sie häufig anders handeln, je nachdem, ob eine Variable ein Array oder ein Hash ist, und nicht nur sagen. In dieser Situation ist eine elegante Redewendung die folgende:
Beachten Sie, dass Sie die
.class
Methode nicht aufrufenitem
.quelle
Sie können verwenden
instance_of?
z.B
quelle
ActiveRecord::Collection
und versuchen,instance_of?(Array)
wird dieses zurückgegebenfalse
, während es zurückgegebenis_a?(Array)
wirdtrue
.Wenn Sie testen möchten, ob ein Objekt streng ist oder a erweitert
Hash
, verwenden Sie:Aber um Rubys Enten-Tippen wertzuschätzen, könnten Sie Folgendes tun:
Dies ist nützlich, wenn Sie nur über die
value[:key]
Syntax auf einen bestimmten Wert zugreifen möchten .quelle
quelle