36

オブジェクトがRubyで反復可能かどうかを確認するにはどうすればよいですか?

つまり、次のように、オブジェクトが反復可能かどうかをきれいにチェックするメソッドが必要です。

def is_iterable(my_object)
  ..
end

メソッド内からクラスに明示的に名前を付ける以外に、どこから始めればよいのかよくわかりません。

編集: 私の目的のために、反復可能はあなたが.eachすることができる何かであるとしましょう。

4

6 に答える 6

47

私の目的のために、反復可能はあなたができることだとしましょう.each

このオブジェクトにこのメソッドがあるかどうかを尋ねることができます

def iterable?(object)
  object.respond_to?(:each)
end
于 2012-05-25T14:59:07.213 に答える
46

すでにいくつかの答えがありますが、 Object#is_a?/ Object#kind_of?の2つの方法があります。およびModule#===

  [].is_a? Enumerable #=> true
  "".is_a? Enumerable #=> false

  Enumerable === [] #=> true
  Enumerable === "" #=> false
于 2012-05-25T15:23:19.810 に答える
10

あなたのより大きな目標とあなたが結果で何をする必要があるかに応じて、これを行うためのいくつかの方法があります。

  1. ダックタイピングを使用して、オブジェクトが#eachに応答するかどうかを確認したい場合は、そのようなメソッドがあるかどうかをオブジェクトに尋ねることができます。

    my_object.respond_to? :each
    
  2. オブジェクトがEnumerableクラスに混在しているかどうかを確認したい場合は、クラスが含まれているかどうかを確認できます。

    my_object.class.include? Enumerable
    
  3. すべての祖先とミックスインのリストが必要な場合は、#ancestorsメソッドが必要です。たとえば、my_objectがEnumerableクラスを継承しているかどうかを確認するには、次のコマンドを呼び出します。

    my_object = []
    my_object.class.ancestors
    => [Array, Enumerable, Object, PP::ObjectMixin, Kernel, BasicObject]
    
    my_object.class.ancestors.include? Enumerable
    => true
    
于 2012-05-25T15:00:37.730 に答える
2

反復可能でない場合でもRange応答するため、範囲の要素が応答することを具体的に確認する必要がありますeachsucc

def iterable?(object)
  return object.begin.respond_to? :succ if object.kind_of? Range
  object.respond_to? :each
end
于 2014-08-26T00:13:17.857 に答える
1

一般的に、eachメソッドが定義されているかどうか、またはEnumerableモジュールがオブジェクトのクラスに含まれているかどうかを確認できます。

my_object.class.include? Enumerable
于 2012-05-25T15:02:24.623 に答える
0

MinitestActiveRecordコンポジションオブジェクトのスタイルテストケース:

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
于 2018-10-11T22:22:35.240 に答える