将Ruby哈希转换为数组而不调用`Hash#to_a`

时间:2012-07-24 16:00:53

标签: ruby arrays hash casting

我使用的Savon gem给了我一个对象或一个数组,在SOAP响应回来之前我无法知道它将会是什么。

为方便起见,我希望将nil响应转换为[],将单个响应转换为[obj],并将数组保留为数组。这可以通过Kernel#Array轻松完成,因此:

> Array nil
=> [] 
> Array 1
=> [1] 
> Array [1,2,3]
=> [1, 2, 3] 

但是,由于Kernel#Array调用了to_a,因此Hash which overrides to_a失败了:

> Array({a: 1})
=> [[:a, 1]]
> Array([{a: 1}, {b: 2}])
=> [{:a=>1}, {:b=>2}]

在上面的第2行,我希望看到[{:a=>1}]

5 个答案:

答案 0 :(得分:3)

如果您使用的是ActiveSupport,则可以执行以下操作:

> Array.wrap({a: 1})
=> [{:a, 1}]
> Array.wrap([{a: 1}, {b: 2}])
=> [{:a=>1}, {:b=>2}]

答案 1 :(得分:2)

>> [nil].compact.flatten(1)
=> []
>> [1].compact.flatten(1)
=> [1]
>> [{a: 1, b: 2}].compact.flatten(1)
=> [{:a=>1, :b=>2}]

答案 2 :(得分:1)

目前,我可以使用自己的Hash#to_a方法绕过straight_to_a

def straight_to_a(o)
  o.kind_of?(Array) ? o : [o].compact
end

因此:

> straight_to_a nil
=> [] 
> straight_to_a 1
=> [1] 
> straight_to_a( {a: 1} )
=> [{:a=>1}]

我希望有一种更简单的方法吗?

答案 3 :(得分:1)

另一张海报建议使用Active Support。如果您不想仅为一个方法为项目添加额外的依赖项,请参阅Active Support Array.wrap的源代码:

class Array
  def self.wrap(object)
    if object.nil?
      []
    elsif object.respond_to?(:to_ary)
      object.to_ary || [object]
    else
      [object]
    end
  end
end

您可以轻松地将此代码添加到您自己的utilities.rbcore_extensions.rb文件中,并将其包含在您的项目中。

答案 4 :(得分:0)

您的解决方案似乎没问题,也许您可​​以尝试基于flatten的内容,例如

def straight_to_a *ary
  ary.flatten(1)
end