Andrew: Estoy llamando a una API y en el JSON vuelvo, si hay varios resultados, obtengo una matriz, pero si solo hay una, obtengo un hash en lugar de una matriz de un solo elemento. ¿Hay un mejor avance que hacer la verificación Array vs Hash?
drhyde
2
¿Entonces obtienes uno [result_hash, another_result_hash]o single_result_hash? ¡Quien haya creado esa API no estaba haciendo un buen trabajo!
Andrew Grimm
2
Tienes razón, Andrew, y apuesto a que es mucho más fácil conseguir que las personas que escribieron la API lo arreglen que probar un hash frente a una matriz.
Olivier 'Ölbaum' Scherler
Tengo la misma situación que @drhyde. En mi caso, el tercero es HTTParty, que después de analizar un archivo XML no tiene forma de decidir cuál es la mejor manera de manejar una situación en la que un elemento puede tener 1 n hijos.
Vale la pena señalar que el "is_a?" El método es verdadero si la clase está en cualquier parte del árbol de ascendencia de los objetos. por ejemplo:
@some_var.is_a?(Object)# => true
lo anterior es cierto si @some_var es una instancia de un hash u otra clase que se deriva de Object. Entonces, si desea una coincidencia estricta en el tipo de clase, utilizando == o instancia_de? El método es probablemente lo que estás buscando.
is_a?es la mejor opción, ya que también regresa truepara subclases.
Fábio Batista
Y, por supuesto, también omites los corchetes, así que @som_var.is_a? Hashtambién funciona :)
Gus Shortz
77
Tenga cuidado, esto realmente podría fastidiarlo si alguien termina pasándole una instancia de ActiveSupport :: HashWithIndifferentAccess. Lo que responde como un hash, pero en realidad no es un Hash. :(
despliega
También me hubieran gustado más respuestas que entraran en detalles con respecto a la escritura de patos, ya que el autor original aparentemente estaba buscando una forma rubí de hacer una verificación de tipo.
NobodysNightmare
3
@unflores ActiveSupport::HashWithIndifferentAccesshereda de Hash, por @some_var.is_a?(Hash)lo tanto, también será cierto en este caso. (Solo tenía la misma pregunta y el caso HashWithIndifferentAccess y me confundí un poco por su comentario ... así que quería aclarar)
Stilzk1n
38
En primer lugar, la mejor respuesta para la pregunta literal es
Hash===@some_var
Pero la pregunta realmente debería haberse respondido mostrando cómo hacer tipear patos aquí. Eso depende un poco del tipo de pato que necesites.
Por lo general, en rubí cuando buscas "tipo", en realidad quieres el "tipo pato" o "¿grazna como un pato?". Vería si responde a cierto método:
@some_var.respond_to?(:each)
Puede iterar sobre @some_var porque responde a: cada
Si realmente quiere saber el tipo y si es Hash o Array, puede hacer lo siguiente:
["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
Esto no funcionará si su código depende del orden de los datos (por ejemplo, si está usando each_with_index). El orden de los elementos es implementado de manera diferente entre hashes y arrays y es diferente entre las versiones de rubí (. Intertwingly.net/slides/2008/oscon/ruby19/22 )
juan2raid
1
@ juan2raid: Si el orden es importante, sortprimero instálelo .
Andrew Grimm
El segundo ejemplo de @Brandon debería convertir la clase a cadena. <br/>["Hash", "Array"].include?(@some_var.class.to_s) #=> check both through instance class
OBCENEIKON
12
Hash===@some_var#=> return Boolean
esto también se puede usar con declaración de caso
En la práctica, a menudo querrá actuar de manera diferente dependiendo de si una variable es una matriz o un hash, no solo una simple indicación. En esta situación, un idioma elegante es el siguiente:
case item
whenArray#do somethingwhenHash#do something elseend
Tenga en cuenta que no llama al .classmétodo item.
¡Tenga en cuenta que esto no funciona para las subclases ! Por ejemplo, si tiene un ActiveRecord::Collectione intente instance_of?(Array), esto volverá false, mientras is_a?(Array)que volverá true.
Tom Lord
0
Si desea probar si un objeto es estrictamente o extiende a Hash, use:
value ={}
value.is_a?(Hash)|| value.is_a?(Array)#=> true
Pero para valorar la escritura del pato de Ruby, podría hacer algo como:
value ={}
value.respond_to?(:[])#=> true
Es útil cuando solo desea acceder a algún valor utilizando la value[:key]sintaxis.
Tenga en cuenta que Array.new["key"]elevará a TypeError.
[result_hash, another_result_hash]
osingle_result_hash
? ¡Quien haya creado esa API no estaba haciendo un buen trabajo!Respuestas:
Solo puedes hacer:
o también algo como:
Vale la pena señalar que el "is_a?" El método es verdadero si la clase está en cualquier parte del árbol de ascendencia de los objetos. por ejemplo:
lo anterior es cierto si @some_var es una instancia de un hash u otra clase que se deriva de Object. Entonces, si desea una coincidencia estricta en el tipo de clase, utilizando == o instancia_de? El método es probablemente lo que estás buscando.
fuente
is_a?
es la mejor opción, ya que también regresatrue
para subclases.@som_var.is_a? Hash
también funciona :)ActiveSupport::HashWithIndifferentAccess
hereda de Hash, por@some_var.is_a?(Hash)
lo tanto, también será cierto en este caso. (Solo tenía la misma pregunta y el caso HashWithIndifferentAccess y me confundí un poco por su comentario ... así que quería aclarar)En primer lugar, la mejor respuesta para la pregunta literal es
Pero la pregunta realmente debería haberse respondido mostrando cómo hacer tipear patos aquí. Eso depende un poco del tipo de pato que necesites.
o
o incluso
puede ser correcto dependiendo de la aplicación.
fuente
Por lo general, en rubí cuando buscas "tipo", en realidad quieres el "tipo pato" o "¿grazna como un pato?". Vería si responde a cierto método:
Puede iterar sobre @some_var porque responde a: cada
Si realmente quiere saber el tipo y si es Hash o Array, puede hacer lo siguiente:
fuente
sort
primero instálelo .["Hash", "Array"].include?(@some_var.class.to_s) #=> check both through instance class
esto también se puede usar con declaración de caso
fuente
Yo uso esto:
Funciona para Hash y ActiveSupport :: HashWithIndifferentAccess.
fuente
En la práctica, a menudo querrá actuar de manera diferente dependiendo de si una variable es una matriz o un hash, no solo una simple indicación. En esta situación, un idioma elegante es el siguiente:
Tenga en cuenta que no llama al
.class
métodoitem
.fuente
Puedes usar
instance_of?
p.ej
fuente
ActiveRecord::Collection
e intenteinstance_of?(Array)
, esto volveráfalse
, mientrasis_a?(Array)
que volverátrue
.Si desea probar si un objeto es estrictamente o extiende a
Hash
, use:Pero para valorar la escritura del pato de Ruby, podría hacer algo como:
Es útil cuando solo desea acceder a algún valor utilizando la
value[:key]
sintaxis.fuente
fuente