在Ruby中,判断变量是散列还是数组的优雅方法是什么?

在Ruby中,判断变量是散列还是数组的优雅方法是什么?,ruby,arrays,hash,Ruby,Arrays,Hash,要检查@some_var是什么,我正在做一个 if @some_var.class.to_s == 'Hash' 我相信有一种更优雅的方法可以检查@some\u var是散列还是数组您可以使用实例 e、 g 您只需执行以下操作: @some_var.class == Hash 或者类似于: @some_var.is_a?(Hash) value = {} value.respond_to?(:[]) #=> true 值得注意的是,如果类位于对象祖先树中的任何位置,“is_a?”

要检查
@some_var
是什么,我正在做一个

if @some_var.class.to_s == 'Hash' 

我相信有一种更优雅的方法可以检查
@some\u var
散列还是
数组

您可以使用
实例

e、 g

您只需执行以下操作:

@some_var.class == Hash
或者类似于:

@some_var.is_a?(Hash)
value = {}
value.respond_to?(:[]) #=> true
值得注意的是,如果类位于对象祖先树中的任何位置,“is_a?”方法是正确的。例如:

@some_var.is_a?(Object)  # => true

如果@some_var是hash或其他源于Object的类的实例,则上述情况成立。那么,如果您想在类类型上进行严格匹配,使用的==或实例_?方法可能就是您要寻找的

通常在ruby中,当你在寻找“type”时,你实际上想要的是“duck type”或“像鸭子一样嘎嘎吗?”。您将看到它是否响应某个方法:

irb(main):005:0> {}.class
=> Hash
irb(main):006:0> [].class
=> Array
@some_var.respond_to?(:each)
您可以迭代@some_var,因为它响应:each

如果您确实想知道类型,并且它是哈希还是数组,则可以执行以下操作:

["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
这也可以与case语句一起使用

case @some_var
when Hash
   ...
when Array
   ...
end

首先,这个字面问题的最佳答案是

Hash === @some_var
但是这个问题真的应该通过在这里演示如何进行duck输入来回答。 这取决于你需要什么样的鸭子

@some_var.respond_to?(:each_pair)

甚至

@some_var.respond_to?(:to_hash)
可能是正确的,具体取决于应用程序。

我使用以下方法:

@var.respond_to?(:keys)

它适用于Hash和ActiveSupport::HashWithInferenceTaccess。

在实践中,您通常希望根据变量是数组还是哈希而采取不同的操作,而不仅仅是告诉。在这种情况下,一个优雅的成语是:

case item
  when Array
   #do something
  when Hash
   #do something else
end

请注意,您没有调用
上的
.class
方法

如果要测试某个对象是严格的还是扩展了
哈希值,请使用:

value = {}
value.is_a?(Hash) || value.is_a?(Array) #=> true
但要使Ruby的duck类型更有价值,您可以执行以下操作:

@some_var.is_a?(Hash)
value = {}
value.respond_to?(:[]) #=> true
当您只想使用
value[:key]
语法访问某个值时,它非常有用

请注意,
Array.new[“key”]
将引发
TypeError


is_a?
是最好的选择,因为它还返回子类的
true
。当然,您也省略了括号,所以
@som_var.is_a?Hash
也可以工作:)小心,如果有人最终向您传递ActiveSupport::HashWithInferenceTaccess的实例,这可能会让您很难过。它的响应类似于散列,但实际上不是散列:(我还希望得到更多关于duck类型的详细答案,因为最初的作者显然是在寻找一种ruby方式来进行类型检查。@unflores
ActiveSupport::hashWithInferenceAccess
继承自Hash,因此
@some_var.is_a?(Hash)
在这种情况下也将返回true。)。(我刚才问了同样的问题和HashWithInferenceAccess案例,从您的评论中感到有点困惑……所以我想澄清一下)如果您的代码依赖于数据的顺序(例如,如果您使用每个_和_索引),这将不起作用。元素的顺序在散列和数组之间的实现方式不同,在ruby版本之间也不同。(@juan2raid:如果顺序很重要,那么首先对其调用
sort
。@Brandon第二个示例应将类转换为字符串。
[“Hash”,“Array”]。包括?(@some_var.class.to_s)#=>通过实例类检查这两种情况
Andrew:我调用了一个API,在JSON中我得到了返回,如果有多个结果,我得到一个数组,但如果只有一个结果,我得到的是散列,而不是一个元素数组。有没有比执行数组vs散列检查更好的前进方式呢?那么你得到的是
[结果\u散列,另一个结果\u散列]
单个结果\u散列
?创建该API的人做得不好!你说得对,Andrew,我打赌让编写API的人来修复它要比测试散列与数组容易得多。我的情况与@drhyde相同。在我的情况下,第三方是HTTParty,它在解析XML文件后没有y来决定处理元素可以有1-n个子元素的情况的最佳方法。您应该观看Avdi Grimms screencast:并可能让cabos回答可接受的问题。请注意,这对子类不起作用!例如,如果您有一个
ActiveRecord::Collection
并尝试
instance\u of?(数组)
然后返回
false
,而
是一个?(数组)
将返回
true
value = {}
value.respond_to?(:[]) #=> true