Andrew: Estou chamando uma API e, no JSON, recebo de volta, se houver vários resultados, obter uma matriz, mas se houver apenas uma, recebo um Hash em vez de uma única matriz. Existe um avanço melhor do que fazer a verificação Array vs Hash?
drhyde
2
Então você pega um [result_hash, another_result_hash]ou single_result_hash? Quem criou essa API não estava fazendo um bom trabalho!
Andrew Grimm
2
Você está certo, Andrew, e aposto que é muito mais fácil conseguir que as pessoas que escreveram a API o corrijam do que testar um hash versus um array.
Olivier 'Ölbaum' Scherler
Eu tenho a mesma situação que @drhyde. No meu caso, a terceira parte é HTTParty que, após analisar um arquivo XML, não tem como decidir qual é a melhor maneira de lidar com uma situação em que um elemento pode ter 1-n filhos.
Vale a pena notar que o "is_a?" O método é verdadeiro se a classe estiver em qualquer lugar da árvore de ascendência dos objetos. por exemplo:
@some_var.is_a?(Object)# => true
o acima é verdadeiro se @some_var for uma instância de um hash ou outra classe que deriva de Object. Então, se você deseja uma correspondência estrita no tipo de classe, use o == ou instance_of? provavelmente é o que você está procurando.
is_a?é a melhor opção, pois também retorna truepara subclasses.
Fábio Batista
E, claro, você também deixar de fora os suportes, por isso @som_var.is_a? Hashfunciona também :)
Gus Shortz
7
Cuidado, isso pode realmente te ferrar se alguém acabar passando uma instância do ActiveSupport :: HashWithIndifferentAccess. O que responde como um hash, mas na verdade não é um hash. :(
unflores
Eu também gostaria de obter mais respostas detalhadas sobre a digitação de patos, já que o autor original aparentemente estava procurando uma maneira ruby de fazer uma verificação de tipo.
NobodysNightmare
3
O @unflores ActiveSupport::HashWithIndifferentAccessherda do Hash, portanto @some_var.is_a?(Hash), retornará true também neste caso. (Eu só tinha o mesmo caso de perguntas e HashWithIndifferentAccess e tem um pouco confuso desde o seu comentário ... então eu queria esclarecer)
Stilzk1n
38
Primeiro de tudo, a melhor resposta para a pergunta literal é
Hash===@some_var
Mas a pergunta realmente deveria ter sido respondida, mostrando como digitar patos aqui. Isso depende um pouco do tipo de pato que você precisa.
Normalmente, em rubi, quando você está procurando por "tipo", na verdade deseja o "tipo de pato" ou "faz é charlatão como um pato?" Você veria se ele responde a um determinado método:
@some_var.respond_to?(:each)
Você pode iterar sobre @some_var porque ele responde a: each
Se você realmente quer saber o tipo e se é Hash ou Array, pode fazer:
["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
Isso não funcionará se o seu código depender da ordem dos dados (por exemplo, se você estiver usando each_with_index). A ordem dos elementos é implementada de forma diferente entre hash e matrizes e é diferente entre as versões de rubi (. Intertwingly.net/slides/2008/oscon/ruby19/22 )
juan2raid
1
@ juan2raid: Se a ordem é importante, ligue sortprimeiro.
Andrew Grimm
@Brandon segundo exemplo deve converter a classe a corda <br/>.["Hash", "Array"].include?(@some_var.class.to_s) #=> check both through instance class
OBCENEIKON
12
Hash===@some_var#=> return Boolean
isso também pode ser usado com a declaração de caso
Na prática, você frequentemente desejará agir de maneira diferente, dependendo se uma variável é uma matriz ou um hash, e não apenas uma mera informação. Nessa situação, um idioma elegante é o seguinte:
case item
whenArray#do somethingwhenHash#do something elseend
Observe que isso não funciona para subclasses ! Por exemplo, se você tiver um ActiveRecord::Collectione tentar instance_of?(Array), isso retornará false, ao passo is_a?(Array)que retornará true.
9788 Tom Ellis
0
Se você deseja testar se um objeto é estritamente ou estende a Hash, use:
value ={}
value.is_a?(Hash)|| value.is_a?(Array)#=> true
Mas, para valorizar a digitação de pato de Ruby, você pode fazer algo como:
value ={}
value.respond_to?(:[])#=> true
É útil quando você deseja acessar apenas algum valor usando a value[:key]sintaxe.
Observe que Array.new["key"]isso aumentará a TypeError.
[result_hash, another_result_hash]
ousingle_result_hash
? Quem criou essa API não estava fazendo um bom trabalho!Respostas:
Você pode apenas fazer:
ou também algo como:
Vale a pena notar que o "is_a?" O método é verdadeiro se a classe estiver em qualquer lugar da árvore de ascendência dos objetos. por exemplo:
o acima é verdadeiro se @some_var for uma instância de um hash ou outra classe que deriva de Object. Então, se você deseja uma correspondência estrita no tipo de classe, use o == ou instance_of? provavelmente é o que você está procurando.
fonte
is_a?
é a melhor opção, pois também retornatrue
para subclasses.@som_var.is_a? Hash
funciona também :)ActiveSupport::HashWithIndifferentAccess
herda do Hash, portanto@some_var.is_a?(Hash)
, retornará true também neste caso. (Eu só tinha o mesmo caso de perguntas e HashWithIndifferentAccess e tem um pouco confuso desde o seu comentário ... então eu queria esclarecer)Primeiro de tudo, a melhor resposta para a pergunta literal é
Mas a pergunta realmente deveria ter sido respondida, mostrando como digitar patos aqui. Isso depende um pouco do tipo de pato que você precisa.
ou
ou mesmo
pode estar certo dependendo da aplicação.
fonte
Normalmente, em rubi, quando você está procurando por "tipo", na verdade deseja o "tipo de pato" ou "faz é charlatão como um pato?" Você veria se ele responde a um determinado método:
Você pode iterar sobre @some_var porque ele responde a: each
Se você realmente quer saber o tipo e se é Hash ou Array, pode fazer:
fonte
sort
primeiro.["Hash", "Array"].include?(@some_var.class.to_s) #=> check both through instance class
isso também pode ser usado com a declaração de caso
fonte
Eu uso isso:
Funciona para Hash e ActiveSupport :: HashWithIndifferentAccess.
fonte
Na prática, você frequentemente desejará agir de maneira diferente, dependendo se uma variável é uma matriz ou um hash, e não apenas uma mera informação. Nessa situação, um idioma elegante é o seguinte:
Observe que você não chama o
.class
métodoitem
.fonte
Você pode usar
instance_of?
por exemplo
fonte
ActiveRecord::Collection
e tentarinstance_of?(Array)
, isso retornaráfalse
, ao passois_a?(Array)
que retornarátrue
.Se você deseja testar se um objeto é estritamente ou estende a
Hash
, use:Mas, para valorizar a digitação de pato de Ruby, você pode fazer algo como:
É útil quando você deseja acessar apenas algum valor usando a
value[:key]
sintaxe.fonte
fonte