最近我偶然发现了" Ruby中的风格元素#3:确定某些东西是一个数组 ".
TL; DR:Array()Ruby中的方法将您放入的任何内容转换为数组并尝试猜测正确的结果应该是什么:
Array(1) # => [1]
Array([1,2]) # => [1,2]
Array(nil) # => []
Run Code Online (Sandbox Code Playgroud)
那Array({a: :b})回报是什么?我假设它返回一个数组,其中哈希值为:[{a: :b}].
但是,哈希直接转换为数组:[:a, :b].
我不只是想将哈希放入数组([{a: :b}]).无论我放入什么内容,我都希望能够返回一个数组.Array()已经这样做了,但它以一种我不期望的方式将哈希转换为数组.
所以,基本上功能应如下所示:
NewFancyArrayMethod({a: :b}) # => [{a: :b}]
NewFancyArrayMethod([{a: :b}, {c: :d}]) # => [{a: :b}, {c: :d}]
Run Code Online (Sandbox Code Playgroud)
第二部分已经完成了Array().
我知道我可以做类似的事情values = [values] unless values.is_a? Array,就像文章指出的那样.但是,我宁愿有一种方法可以从我那里抽象出这种转换Array().唯一的问题是以Array()不同于任何其他"单个"值(String,Integer,Object等)的方式处理哈希.我根本不希望针对不同的情况进行不同的处理.
那
Array({a: :b})回报是什么?我假设它返回一个数组,其中哈希值为:[{a: :b}].
你的假设是错误的.通过尝试(按此顺序)Kernel#Array转换参数arg:
arg.to_aryarg.to_a[arg]例子:
Array(1) #=> [1]
Run Code Online (Sandbox Code Playgroud)
这是因为(3).没有Fixnum#to_ary或Fixnum#to_a
Array([1, 2]) #=> [1, 2]
Run Code Online (Sandbox Code Playgroud)
[[1, 2]]由于(1),这不会返回.Array#to_ary回报self
Array(nil) #=> []
Run Code Online (Sandbox Code Playgroud)
[nil]由于(2),这不会返回.没有,NilClass#to_ary但有NilClass#to_a:"总是返回一个空数组."
Array({a: :b}) #=> [[:a, :b]]
Run Code Online (Sandbox Code Playgroud)
像Array(nil)这种没有返回[{a: :b}],因为(2).没有,Hash#to_ary但有Hash#to_a:"将hsh转换为[key,value]数组的嵌套数组."
Array(Time.now) #=> [33, 42, 17, 22, 8, 2013, 4, 234, true, "CEST"]
Run Code Online (Sandbox Code Playgroud)
这正在Time#to_a回归...... "时间价值的十元素数组"
结论:
Kernel#Array按预期工作,Hash#to_a是罪魁祸首.(或to_a一般而言)
我希望有一个功能,无论我放入什么,都会返回一个数组.
Hash并且Array是不同的对象.您可以检查类型(Kernel#Array也是这样):
def hash_to_array(h)
h.is_a?(Array) ? h : [h]
end
Run Code Online (Sandbox Code Playgroud)
或者扩展Hash(甚至Object)和Array:
class Hash # or Object
def my_to_a
[self]
end
end
class Array
def my_to_a
self
end
end
Run Code Online (Sandbox Code Playgroud)
请参阅备注实现的注释.