如果给定键不存在,则Hash#slice like返回nil的方法

时间:2015-07-29 20:53:15

标签: ruby-on-rails ruby

我在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)

不关心哈希的顺序。

4 个答案:

答案 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