数组方法与哈希

时间:2017-12-05 11:31:59

标签: arrays ruby activesupport

我有一个对象(从和API返回),它是散列或散列数组。如果它不是一个数组,我想把它包含在一个数组中。

我尝试在其上应用Array,它以预期的方式运行数字或数组:

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

但是哈希失败了:

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

应为[{:a=>1}]

或者,我可以添加一个类型检查:

responses = [responses] if responses.is_a?(Hash)

有更好的解决方案吗?

3 个答案:

答案 0 :(得分:2)

正如@mudasobwa所说,[responses].flatten可能是最干净的解决方案:

[{a: 1}].flatten           #=> [{:a=>1}]
[[{a: 1}, {b: 2}]].flatten #=> [{:a=>1}, {:b=>2}]

显然,这种不一致的响应格式不是一个很好的API设计;但不幸的是,与外部资源合作的本质......

如果上面数组中的每个哈希确实表示一个唯一的对象,那么我将保留该代码。但是,如果您对单个实体的每个属性实际使用不同的哈希值(?!),那么您可以按如下方式进一步清理API响应:

[{a: 1}].flatten.reduce(:merge)           #=> {:a=>1}
[[{a: 1}, {b: 2}]].flatten.reduce(:merge) #=> {:a=>1, :b=>2}

答案 1 :(得分:2)

ActiveSupport引入了Array#wrap,它完全符合您的要求:

Array.wrap(responses)

我个人更喜欢从不使用任何Rails助手,原因很多,所以我会坚持使用[responses].flatten,或者更好地使用最明确的版本:

case responses
when Hash then [responses]
when Array then responses
else raise "shit happened"
end

答案 2 :(得分:1)

  

如果它不是一个数组,我想将它括在一个数组中。

怎么样:

result = [result] unless result.is_a? Array

或者,使用try_convert

result = Array.try_convert(result) || [result]