【问题标题】:Hash#slice like method that returns nil if given key are not present如果给定键不存在,则返回 nil 的类似 Hash#slice 的方法
【发布时间】:2015-07-29 20:53:15
【问题描述】:

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

不关心哈希的顺序。

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    我会使用您感兴趣的术语的reduce

    hash = {a: 1, b: 2, d: 4}
    [:a, :c, :d].reduce({}) {|h, k| h[k] = hash[k]; h }
    

    【讨论】:

      【解决方案2】:

      另一种选择:

      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}
      

      【讨论】:

        【解决方案3】:

        这是我的解决方案;它从具有nil 值的keys 数组创建一个新的哈希,并将其与切片的结果合并:

        > Hash[keys.zip].merge(hash.slice(*keys))
         => {:a=>1, :c=>nil, :d=>4}
        

        【讨论】:

          【解决方案4】:

          如果您不喜欢使用reduce(尽管我喜欢),另一种方法是将键映射到元组数组,然后调用to_h。像这样:

          hash = {a: 1, b: 2, d: 4}
          [:a, :c, :d].map{|k| [k, hash[k]]}.to_h
          

          【讨论】:

            猜你喜欢
            • 2021-04-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-11-19
            • 1970-01-01
            • 2022-11-11
            • 2019-05-23
            相关资源
            最近更新 更多