如何检查对象在 Ruby 中是否可迭代?
也就是说,我想要一个干净地检查对象是否可迭代的方法,如下所示:
def is_iterable(my_object)
..
end
我真的不确定从方法中显式命名类的不足从哪里开始。
编辑: 出于我的目的,假设 iterable 是你可以做的事情 .each 。
如何检查对象在 Ruby 中是否可迭代?
也就是说,我想要一个干净地检查对象是否可迭代的方法,如下所示:
def is_iterable(my_object)
..
end
我真的不确定从方法中显式命名类的不足从哪里开始。
编辑: 出于我的目的,假设 iterable 是你可以做的事情 .each 。
就我的目的而言,假设可迭代是您可以做的事情
.each
。
你可以问这个对象是否有这个方法
def iterable?(object)
object.respond_to?(:each)
end
您已经得到了一些答案,但这里还有另外两种方法,Object#is_a?/Object#kind_of? 和模块#===:
[].is_a? Enumerable #=> true
"".is_a? Enumerable #=> false
Enumerable === [] #=> true
Enumerable === "" #=> false
有多种方法可以做到这一点,具体取决于您的更大目标以及您需要对结果做什么。
如果您只想使用鸭子类型来查看对象是否响应#each,那么您可以只询问对象是否有这样的方法。
my_object.respond_to? :each
如果您想了解对象是否混合在 Enumerable 类中,您可以检查该类是否包含。
my_object.class.include? Enumerable
如果你想要所有祖先和 mixin 的列表,你需要#ancestors方法。例如,要查看my_object是否继承自 Enumerable 类,您可以调用:
my_object = []
my_object.class.ancestors
=> [Array, Enumerable, Object, PP::ObjectMixin, Kernel, BasicObject]
my_object.class.ancestors.include? Enumerable
=> true
因为即使在不可迭代时也会Range
响应,所以您需要专门检查 Range 的元素是否响应each
succ
def iterable?(object)
return object.begin.respond_to? :succ if object.kind_of? Range
object.respond_to? :each
end
在一般情况下,您可以检查是否each
定义了方法,或者Enumerable
模块是否包含在对象的类中:
my_object.class.include? Enumerable
Minitest
ActiveRecord
-组合对象的样式测试用例:
def test_iterates_over_invoice_items
invoice = Invoice.new(items: [InvoiceItem.new(description: 'test')])
iteration_count = 0
invoice.each do |invoice_item|
assert_equal 'test', invoice_item.description
iteration_count += 1
end
assert_equal 1, iteration_count
end