What is a elegant way in Ruby to tell if a variable is a Hash or an Array?
RubyArraysHashRuby Problem Overview
To check what @some_var
is, I am doing a
if @some_var.class.to_s == 'Hash'
I am sure there is a more elegant way to check if @some_var
is a Hash
or an Array
.
Ruby Solutions
Solution 1 - Ruby
You can just do:
@some_var.class == Hash
or also something like:
@some_var.is_a?(Hash)
It's worth noting that the "is_a?" method is true if the class is anywhere in the objects ancestry tree. for instance:
@some_var.is_a?(Object) # => true
the above is true if @some_var is an instance of a hash or other class that stems from Object. So, if you want a strict match on the class type, using the == or instance_of? method is probably what you're looking for.
Solution 2 - Ruby
First of all, the best answer for the literal question is
Hash === @some_var
But the question really should have been answered by showing how to do duck-typing here. That depends a bit on what kind of duck you need.
@some_var.respond_to?(:each_pair)
or
@some_var.respond_to?(:has_key?)
or even
@some_var.respond_to?(:to_hash)
may be right depending on the application.
Solution 3 - Ruby
Usually in ruby when you are looking for "type" you are actually wanting the "duck-type" or "does is quack like a duck?". You would see if it responds to a certain method:
@some_var.respond_to?(:each)
You can iterate over @some_var because it responds to :each
If you really want to know the type and if it is Hash or Array then you can do:
["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
Solution 4 - Ruby
Hash === @some_var #=> return Boolean
this can also be used with case statement
case @some_var
when Hash
...
when Array
...
end
Solution 5 - Ruby
I use this:
@var.respond_to?(:keys)
It works for Hash and ActiveSupport::HashWithIndifferentAccess.
Solution 6 - Ruby
In practice, you will often want to act differently depending on whether a variable is an Array or a Hash, not just mere tell. In this situation, an elegant idiom is the following:
case item
when Array
#do something
when Hash
#do something else
end
Note that you don't call the .class
method on item
.
Solution 7 - Ruby
You can use instance_of?
e.g
@some_var.instance_of?(Hash)
Solution 8 - Ruby
If you want to test if an object is strictly or extends a Hash
, use:
value = {}
value.is_a?(Hash) || value.is_a?(Array) #=> true
But to make value of Ruby's duck typing, you could do something like:
value = {}
value.respond_to?(:[]) #=> true
It is useful when you only want to access some value using the value[:key]
syntax.
> Please note that Array.new["key"]
will raise a TypeError
.
Solution 9 - Ruby
irb(main):005:0> {}.class
=> Hash
irb(main):006:0> [].class
=> Array