Ruby:Object.to_a替代品
我需要将传入的参数(单个对象或集合)转换为Array。 我不知道论证是什么。 如果它已经是一个数组,我想保留它,否则从中创建一个单元素数组。 我想要允许两个method(:objs => obj)
和method(:objs => [obj1, obj2])
这似乎是最好的方法(Array#to_a返回self):
arg = arg.to_a
但ruby文档称Object#to_a
很快就会过时 。 有方便的更换吗?
还有比这更简洁的东西吗?
arg = arg.respond_to?(:to_a) ? arg.to_a : [arg]
使用方法Kernel#Array :
Array([1,2,3]) #=> [1, 2, 3] Array(123) #=> [123]
是的,它起初可能看起来像一个类,但这实际上是一个以大写字母开头的方法。
哇,有人只是暗示了一个非常古老的线索。 :-O但是因为我还没有看到它包含在内,所以我将为完整性添加一条方法:
arg = [*arg]
如果它已经是一个数组(因此删除了一个嵌套级别)或创建一个参数数组,这将抛出该参数:
arg = [1,2,3] [*arg] #=> [1, 2, 3] arg = 1 [*arg] #=> [1]
似乎只推荐使用Object.to_a
,删除默认的to_a
并强制每个类定义自己的(例如, Hash.to_a
)。
self.to_a #=> -:1: warning: default `to_a' will be obsolete "hello".to_a #=> ["hello"] Time.new.to_a #=> [39, 54, 8, 9, 4, 2003, 3, 99, true, "CDT"] h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300 } h.to_a #=> [["a", 100], ["c", 300], ["d", 400]]
如果您的参数是Object
的实例,请尝试:
Hash.new(obj).to_a
@Daniel [对Ollivier的评论]: 重点是我不知道论证是什么。 如果它已经是一个数组,我想保留它,否则创建一个单元素数组。
如果是这种情况,请尝试:
obj = [obj] if !obj.is_a?(Array)
如果更适合问题,你可以采取鸭子打字方式,列出你需要的所有方法,并检查对象是否已经拥有它们,如果没有,使它成为一个数组:
[:[], :each, :etc...].all? { |m| obj.respond_to? m } ? obj : [obj]
优点是您可以为对象提供机会来实现索引访问的自己的语义。
我不确定这是否有帮助,但我经常需要的不是arg是一个数组,而是arg响应每个。
arg = [arg] unless arg.respond_to? :each
我做了很多,总是使用:
arg = [arg] unless arg.is_a?(Array)
虽然如果你知道你永远不会将数组作为单独的参数传递,你也可以这样做:
arg = [arg].flatten
那么Array.new(1,arg)呢?