Andrew: J'appelle une API et dans le JSON je reviens, s'il y a plusieurs résultats, j'obtiens un tableau, mais s'il n'y en a qu'un, j'obtiens un hachage plutôt qu'un seul élément. Y a-t-il un meilleur avant que de faire la vérification Array vs Hash?
drhyde
2
Alors vous obtenez soit [result_hash, another_result_hash]ou single_result_hash? Celui qui a créé cette API ne faisait pas du bon travail!
Andrew Grimm
2
Vous avez raison, Andrew, et je parie qu'il est beaucoup plus facile d'amener les gens qui ont écrit l'API à le réparer que de tester un hachage par rapport à un tableau.
Olivier 'Ölbaum' Scherler
j'ai la même situation que @drhyde. Dans mon cas, le tiers est HTTParty qui, après avoir analysé un fichier XML, n'a aucun moyen de décider quelle est la meilleure façon de gérer une situation où un élément peut avoir 1-n enfants.
Il convient de noter que le "is_a?" La méthode est vraie si la classe est n'importe où dans l'arborescence d'ascendance des objets. par exemple:
@some_var.is_a?(Object)# => true
ce qui précède est vrai si @some_var est une instance d'un hachage ou d'une autre classe qui provient d'Object. Donc, si vous voulez une correspondance stricte sur le type de classe, utilisez le == ou instance_of? La méthode est probablement ce que vous recherchez.
is_a?est la meilleure option, car elle renvoie également truepour les sous-classes.
Fábio Batista
Et, bien sûr, vous laissez également les parenthèses, ça @som_var.is_a? Hashmarche aussi :)
Gus Shortz
7
Attention, cela pourrait vraiment vous déranger si quelqu'un finit par vous passer une instance d'ActiveSupport :: HashWithIndifferentAccess. Qui répond comme un hachage, mais n'est en fait pas un hachage. :(
unflores
J'aurais également aimé plus de réponses détaillées concernant la saisie de canard, puisque l'auteur original cherchait apparemment une manière rubis de faire une vérification de type.
NobodysNightmare
3
@unflores ActiveSupport::HashWithIndifferentAccesshérite de Hash, donc @some_var.is_a?(Hash)retournera true dans ce cas également. (Je viens d'avoir la même question et le cas HashWithIndifferentAccess et j'ai été un peu confus à cause de votre commentaire ... alors je voulais clarifier)
Stilzk1n
38
Tout d'abord, la meilleure réponse à la question littérale est
Hash===@some_var
Mais la question aurait vraiment dû être répondue en montrant comment faire du typage canard ici. Cela dépend un peu du type de canard dont vous avez besoin.
Habituellement, en rubis, lorsque vous recherchez «type», vous voulez en fait le «type canard» ou «est-ce que charlatan est comme un canard? Vous verriez s'il répond à une certaine méthode:
@some_var.respond_to?(:each)
Vous pouvez parcourir @some_var car il répond à: each
Si vous voulez vraiment connaître le type et s'il s'agit de Hash ou Array, vous pouvez faire:
["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
Cela ne fonctionnera pas si votre code dépend de l'ordre des données (par exemple, si vous utilisez each_with_index). L'ordre des éléments est mis en œuvre différemment entre les hash et les tableaux et il est différent entre les versions de rubis (. Intertwingly.net/slides/2008/oscon/ruby19/22 )
juan2raid
1
@ juan2raid: Si l'ordre est important, appelez- sortle d'abord.
Andrew Grimm
@Brandon deuxième exemple devrait convertir la classe en chaîne. <br/>["Hash", "Array"].include?(@some_var.class.to_s) #=> check both through instance class
OBCENEIKON
12
Hash===@some_var#=> return Boolean
cela peut également être utilisé avec l'instruction case
En pratique, vous voudrez souvent agir différemment selon que la variable est un tableau ou un hachage, et pas seulement un simple tell. Dans cette situation, un idiome élégant est le suivant:
case item
whenArray#do somethingwhenHash#do something elseend
Notez que vous n'appelez pas la .classméthode item.
Notez que cela ne fonctionne pas pour les sous-classes ! Par exemple, si vous avez un ActiveRecord::Collectionet essayez, instance_of?(Array)cela reviendra false, alors que vous is_a?(Array)reviendrez true.
Tom Lord
0
Si vous voulez tester si un objet est strictement ou étend a Hash, utilisez:
value ={}
value.is_a?(Hash)|| value.is_a?(Array)#=> true
Mais pour valoriser le typage du canard de Ruby, vous pouvez faire quelque chose comme:
value ={}
value.respond_to?(:[])#=> true
C'est utile lorsque vous ne souhaitez accéder qu'à une valeur en utilisant la value[:key]syntaxe.
Veuillez noter que Array.new["key"]cela augmentera un TypeError.
[result_hash, another_result_hash]
ousingle_result_hash
? Celui qui a créé cette API ne faisait pas du bon travail!Réponses:
Vous pouvez simplement faire:
ou aussi quelque chose comme:
Il convient de noter que le "is_a?" La méthode est vraie si la classe est n'importe où dans l'arborescence d'ascendance des objets. par exemple:
ce qui précède est vrai si @some_var est une instance d'un hachage ou d'une autre classe qui provient d'Object. Donc, si vous voulez une correspondance stricte sur le type de classe, utilisez le == ou instance_of? La méthode est probablement ce que vous recherchez.
la source
is_a?
est la meilleure option, car elle renvoie égalementtrue
pour les sous-classes.@som_var.is_a? Hash
marche aussi :)ActiveSupport::HashWithIndifferentAccess
hérite de Hash, donc@some_var.is_a?(Hash)
retournera true dans ce cas également. (Je viens d'avoir la même question et le cas HashWithIndifferentAccess et j'ai été un peu confus à cause de votre commentaire ... alors je voulais clarifier)Tout d'abord, la meilleure réponse à la question littérale est
Mais la question aurait vraiment dû être répondue en montrant comment faire du typage canard ici. Cela dépend un peu du type de canard dont vous avez besoin.
ou
ou même
peut avoir raison selon l'application.
la source
Habituellement, en rubis, lorsque vous recherchez «type», vous voulez en fait le «type canard» ou «est-ce que charlatan est comme un canard? Vous verriez s'il répond à une certaine méthode:
Vous pouvez parcourir @some_var car il répond à: each
Si vous voulez vraiment connaître le type et s'il s'agit de Hash ou Array, vous pouvez faire:
la source
sort
le d'abord.["Hash", "Array"].include?(@some_var.class.to_s) #=> check both through instance class
cela peut également être utilisé avec l'instruction case
la source
J'utilise ceci:
Cela fonctionne pour Hash et ActiveSupport :: HashWithIndifferentAccess.
la source
En pratique, vous voudrez souvent agir différemment selon que la variable est un tableau ou un hachage, et pas seulement un simple tell. Dans cette situation, un idiome élégant est le suivant:
Notez que vous n'appelez pas la
.class
méthodeitem
.la source
Vous pouvez utiliser
instance_of?
par exemple
la source
ActiveRecord::Collection
et essayez,instance_of?(Array)
cela reviendrafalse
, alors que vousis_a?(Array)
reviendreztrue
.Si vous voulez tester si un objet est strictement ou étend a
Hash
, utilisez:Mais pour valoriser le typage du canard de Ruby, vous pouvez faire quelque chose comme:
C'est utile lorsque vous ne souhaitez accéder qu'à une valeur en utilisant la
value[:key]
syntaxe.la source
la source