我有一个接受单个对象或对象集合的方法。检测传入的内容是否为Enumerable的正确方法是什么?我目前正在做以下事情(有效,但我不确定这是正确的方法):
def foo(bar)
if bar.respond_to? :map
# loop over it
else
# single object
end
end
答案 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
通常不是一个好主意。特别是,Hash
是Enumerable
,但在大多数情况下,它应被视为单个对象。
通常最好区分单个对象和类似数组参数。这就是Ruby经常做的事情。最好的方法是检查是否arg.respond_to? :to_ary
。如果确实如此,那么Array
的所有方法都应该可用,如果不将其视为单个对象。
如果您确实要查看Enumerable
,可以测试arg.is_a? Enumerable
,但可以认为Hash
是Enumerable
,Lazy
枚举者也是如此({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) # => []