如何检查对象是否可以在Ruby中迭代?
也就是说,我想要一个干净地检查对象是否可迭代的方法,如下所示:
def is_iterable(my_object)
..
end
我真的不确定从这个方法中明确命名类的这一短暂开始。
修改: 为了我的目的,让我们说可迭代是你可以做的事情。每次。
答案 0 :(得分:43)
就我的目的而言,我们假设您可以
.each
来执行迭代。
您可以询问此对象是否具有此方法
def iterable?(object)
object.respond_to? :each
end
答案 1 :(得分:43)
您已经有了一些答案,但还有两种方法,Object#is_a?/Object#kind_of?和Module#===:
[].is_a? Enumerable #=> true
"".is_a? Enumerable #=> false
Enumerable === [] #=> true
Enumerable === "" #=> false
答案 2 :(得分:9)
有很多方法可以做到这一点,具体取决于你的更大目标以及你需要对结果做些什么。
如果您只想使用duck typing来查看对象是否响应 #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
答案 3 :(得分:1)
一般情况下,您可以检查是否定义了each
方法,或者对象的类中是否包含Enumerable
模块:
my_object.class.include? Enumerable
答案 4 :(得分:1)
因为Range
响应each
即使它不可迭代,您需要专门检查Range的元素是否响应succ
def iterable?(object)
return object.begin.respond_to? :succ if object.kind_of? Range
object.respond_to? :each
end
答案 5 :(得分:0)
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