Andrew: Wywołuję API iw JSON otrzymuję z powrotem, jeśli jest wiele wyników, otrzymuję Array, ale jeśli jest tylko jeden, otrzymuję Hash, a nie pojedynczy element Array. Czy jest lepszy naprzód niż wykonanie testu Array vs Hash?
drhyde
2
Więc masz albo [result_hash, another_result_hash]albo single_result_hash? Ktokolwiek stworzył to API, nie wykonał dobrej roboty!
Andrew Grimm
2
Masz rację, Andrew, i założę się, że o wiele łatwiej jest przekonać ludzi, którzy napisali interfejs API, aby to naprawili, niż przetestować wartość skrótu w porównaniu z tablicą.
Olivier 'Ölbaum' Scherler
mam taką samą sytuację jak @drhyde. W moim przypadku stroną trzecią jest HTTParty, który po przeanalizowaniu pliku XML nie ma możliwości zdecydowania, jaki jest najlepszy sposób obsługi sytuacji, w której element może mieć 1-n dzieci.
Warto zauważyć, że „is_a?” metoda jest prawdą, jeśli klasa znajduje się w dowolnym miejscu w drzewie przodków obiektów. na przykład:
@some_var.is_a?(Object)# => true
powyższe jest prawdziwe, jeśli @some_var jest instancją skrótu lub innej klasy, która pochodzi z Object. Tak więc, jeśli chcesz ścisłego dopasowania do typu klasy, używając == lub instance_of? metoda jest prawdopodobnie tym, czego szukasz.
is_a?jest najlepszą opcją, ponieważ zwraca również truedla podklas.
Fábio Batista
I oczywiście pomijasz też nawiasy, więc @som_var.is_a? Hashteż działa :)
Gus Shortz
7
Uważaj, to może cię naprawdę schrzanić, jeśli ktoś przekaże Ci wystąpienie ActiveSupport :: HashWithIndifferentAccess. Który reaguje jak hash, ale w rzeczywistości nie jest hashem. :(
unflores
Chciałbym również, aby więcej odpowiedzi zawierało szczegóły dotyczące pisania kaczkami, ponieważ pierwotny autor najwyraźniej szukał rubinowego sposobu sprawdzania typu.
NobodysNightmare
3
@unflores ActiveSupport::HashWithIndifferentAccessdziedziczy po Hash, dlatego też @some_var.is_a?(Hash)w tym przypadku zwróci wartość true. (Właśnie miałem to samo pytanie i sprawę HashWithIndifferentAccess i trochę się pomyliłeś po twoim komentarzu ... więc chciałem wyjaśnić)
Stilzk1n
38
Przede wszystkim najlepszą odpowiedzią na dosłowne pytanie jest
Hash===@some_var
Ale na pytanie naprawdę należało odpowiedzieć, pokazując, jak tutaj pisać kaczkę. To zależy trochę od tego, jakiego rodzaju kaczki potrzebujesz.
Zwykle w rubinowym, gdy szukasz „typu”, w rzeczywistości chcesz „typ kaczki” lub „czy to szarlatan jak kaczka?”. Zobaczysz, czy reaguje na określoną metodę:
@some_var.respond_to?(:each)
Możesz iterować po @some_var, ponieważ odpowiada na: each
Jeśli naprawdę chcesz znać typ i czy jest to Hash lub Array, możesz zrobić:
["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
To nie zadziała, jeśli twój kod jest zależny od kolejności danych (np. Jeśli używasz each_with_index). Kolejność elementów jest różnie zaimplementowana między hashesami i tablicami i jest różna między wersjami ruby. ( Intertwingly.net/slides/2008/oscon/ruby19/22 )
juan2raid
1
@ juan2raid: Jeśli porządek jest ważny, najpierw zadzwoń sortdo niego.
Andrew Grimm
Drugi przykład @Brandon powinien przekonwertować klasę na ciąg. <br/>["Hash", "Array"].include?(@some_var.class.to_s) #=> check both through instance class
W praktyce często będziesz chciał zachowywać się inaczej w zależności od tego, czy zmienna jest tablicą, czy skrótem, a nie tylko zwykłym powiedzeniem. W tej sytuacji elegancki idiom jest następujący:
case item
whenArray#do somethingwhenHash#do something elseend
Zauważ, że to nie działa w przypadku podklas ! Na przykład, jeśli masz ActiveRecord::Collectioni spróbuj, instance_of?(Array)to zwróci false, podczas gdy is_a?(Array)zwróci true.
Tom Lord
0
Jeśli chcesz sprawdzić, czy obiekt jest ściśle lub rozszerza a Hash, użyj:
value ={}
value.is_a?(Hash)|| value.is_a?(Array)#=> true
Ale aby zyskać wartość pisania kaczego Rubiego, możesz zrobić coś takiego:
value ={}
value.respond_to?(:[])#=> true
Jest to przydatne, gdy chcesz uzyskać dostęp tylko do niektórych wartości za pomocą value[:key]składni.
[result_hash, another_result_hash]
albosingle_result_hash
? Ktokolwiek stworzył to API, nie wykonał dobrej roboty!Odpowiedzi:
Możesz po prostu zrobić:
lub też coś takiego:
Warto zauważyć, że „is_a?” metoda jest prawdą, jeśli klasa znajduje się w dowolnym miejscu w drzewie przodków obiektów. na przykład:
powyższe jest prawdziwe, jeśli @some_var jest instancją skrótu lub innej klasy, która pochodzi z Object. Tak więc, jeśli chcesz ścisłego dopasowania do typu klasy, używając == lub instance_of? metoda jest prawdopodobnie tym, czego szukasz.
źródło
is_a?
jest najlepszą opcją, ponieważ zwraca równieżtrue
dla podklas.@som_var.is_a? Hash
też działa :)ActiveSupport::HashWithIndifferentAccess
dziedziczy po Hash, dlatego też@some_var.is_a?(Hash)
w tym przypadku zwróci wartość true. (Właśnie miałem to samo pytanie i sprawę HashWithIndifferentAccess i trochę się pomyliłeś po twoim komentarzu ... więc chciałem wyjaśnić)Przede wszystkim najlepszą odpowiedzią na dosłowne pytanie jest
Ale na pytanie naprawdę należało odpowiedzieć, pokazując, jak tutaj pisać kaczkę. To zależy trochę od tego, jakiego rodzaju kaczki potrzebujesz.
lub
lub nawet
może mieć rację w zależności od aplikacji.
źródło
Zwykle w rubinowym, gdy szukasz „typu”, w rzeczywistości chcesz „typ kaczki” lub „czy to szarlatan jak kaczka?”. Zobaczysz, czy reaguje na określoną metodę:
Możesz iterować po @some_var, ponieważ odpowiada na: each
Jeśli naprawdę chcesz znać typ i czy jest to Hash lub Array, możesz zrobić:
źródło
sort
do niego.["Hash", "Array"].include?(@some_var.class.to_s) #=> check both through instance class
można tego również użyć z instrukcją case
źródło
Używam tego:
Działa dla Hash i ActiveSupport :: HashWithIndifferentAccess.
źródło
W praktyce często będziesz chciał zachowywać się inaczej w zależności od tego, czy zmienna jest tablicą, czy skrótem, a nie tylko zwykłym powiedzeniem. W tej sytuacji elegancki idiom jest następujący:
Pamiętaj, że nie wywołujesz
.class
metodyitem
.źródło
Możesz użyć
instance_of?
na przykład
źródło
ActiveRecord::Collection
i spróbuj,instance_of?(Array)
to zwrócifalse
, podczas gdyis_a?(Array)
zwrócitrue
.Jeśli chcesz sprawdzić, czy obiekt jest ściśle lub rozszerza a
Hash
, użyj:Ale aby zyskać wartość pisania kaczego Rubiego, możesz zrobić coś takiego:
Jest to przydatne, gdy chcesz uzyskać dostęp tylko do niektórych wartości za pomocą
value[:key]
składni.źródło
źródło