检测Ruby中是否有可枚举的东西

时间:2013-07-18 17:19:51

标签: ruby

我有一个接受单个对象或对象集合的方法。检测传入的内容是否为Enumerable的正确方法是什么?我目前正在做以下事情(有效,但我不确定这是正确的方法):

def foo(bar)
  if bar.respond_to? :map
    # loop over it
  else
    # single object
  end
end

5 个答案:

答案 0 :(得分:8)

我会使用is_a?

bar.is_a? Enumerable

但是有一个更好的方法来获取单个对象或集合,假设调用者知道他们传入了哪一个。使用splat:

def foo(*args)
  args.each do |arg|
    …
  end
end

然后,您可以将其称为foo(single_arg)foo(arg1, arg2)foo(*argv)

答案 1 :(得分:4)

我取决于您的确切需求,但区分单个对象和Enumerable通常不是一个好主意。特别是,HashEnumerable,但在大多数情况下,它应被视为单个对象。

通常最好区分单个对象和类似数组参数。这就是Ruby经常做的事情。最好的方法是检查是否arg.respond_to? :to_ary。如果确实如此,那么Array的所有方法都应该可用,如果不将其视为单个对象。

如果您确实要查看Enumerable,可以测试arg.is_a? Enumerable,但可以认为HashEnumerableLazy枚举者也是如此({1}}并且在他们身上调用map甚至不会给你一个数组!)

答案 2 :(得分:3)

如果您的目的是循环它,那么标准方法是确保它是一个数组。你可以无条件地这样做。

def foo(bar)
  [*bar] # Loop over it. It is ensured to be an array.
end

答案 3 :(得分:1)

如何一次处理单件物品或收藏品?

[*bar].each { |item| puts item }

无论bar是单个项目还是数组或哈希或其他任何内容,这都将有效。这可能不适合使用哈希,但是使用数组它可以很好地工作。

答案 4 :(得分:1)

确保某些内容为Array的另一种方法是使用Array“函数(技术上仍然是一种方法):

def foo(bar)
  Array(bar).map { |o| … }
end

Array会将数组保留为数组,并将单个元素转换为数组:

Array(["foo"]) # => ["foo"]
Array("foo")   # => ["foo"]
Array(nil)     # => []