我在rails环境中使用Hash#slice
方法。
slice
方法的工作原理如下:
{ a: 1, b: 2, d: 4 }.slice(:a, :c, :d)
=> {:a=>1, :d=>4}
但是如果给定的密钥不存在,我想返回nil
,如下所示:
{ a: 1, b: 2, d: 4 }.slice(:a, :c, :d)
=> {:a=>1, :c=>nil, :d=>4}
这是我为函数编写的,是否有更好的方法来编写这个函数?
hash = {a: 1, b: 2, d: 4}
keys = [:a, :c, :d]
keys_not_present = keys.map { |key| key unless hash.has_key?(key) }.compact
keys_not_present = keys_not_present.zip([nil]*keys_not_present.size).to_h
hash.slice(*keys).merge(keys_not_present)
不关心哈希的顺序。
答案 0 :(得分:2)
我会使用您感兴趣的reduce
条款:
hash = {a: 1, b: 2, d: 4}
[:a, :c, :d].reduce({}) {|h, k| h[k] = hash[k]; h }
答案 1 :(得分:1)
另一种选择:
hash = {a: 1, b: 2, d: 4}
[:a, :c, :d].collect { |k| [k, hash[k]] }.to_h
=> {:a=>1, :c=>nil, :d=>4}
您可以将补丁Hash
添加为方法:
class Hash
def my_slice(*keys)
keys.collect { |k| [k, self[k]] }.to_h
end
end
{a: 1, b: 2, d: 4}.my_slice(:a, :c, :d)
=> {:a=>1, :c=>nil, :d=>4}
答案 2 :(得分:1)
这是我的解决方案;它从keys
数组创建一个带有nil
值的新Hash,并将其与切片的结果合并:
> Hash[keys.zip].merge(hash.slice(*keys))
=> {:a=>1, :c=>nil, :d=>4}
答案 3 :(得分:0)
如果您不喜欢使用reduce(尽管我很喜欢),另一种方法是将键映射到元组数组,然后调用to_h。像这样:
hash = {a: 1, b: 2, d: 4}
[:a, :c, :d].map{|k| [k, hash[k]]}.to_h