首页 文章

如何从Hash中删除一个键并获取Ruby / Rails中的剩余哈希?

提问于
浏览
471

要向Hash添加新对,我会:

{:a => 1, :b => 2}.merge!({:c => 3})   #=> {:a => 1, :b => 2, :c => 3}

是否有类似的方法从哈希删除密钥?

这有效:

{:a => 1, :b => 2}.reject! { |k| k == :a }   #=> {:b => 2}

但我希望有类似的东西:

{:a => 1, :b => 2}.delete!(:a)   #=> {:b => 2}

重要的是返回值将是剩余的哈希值,因此我可以执行以下操作:

foo(my_hash.reject! { |k| k == my_key })

在一行 .

13 回答

  • 11

    如果删除返回散列的删除对,那就太好了 . 我这样做:

    hash = {a: 1, b: 2, c: 3}
    {b: hash.delete(:b)} # => {:b=>2}
    hash  # => {:a=>1, :c=>3}
    
  • 31

    这也可以: hash[hey] = nil

  • 146
    #in lib/core_extensions.rb
    class Hash
      #pass single or array of keys, which will be removed, returning the remaining hash
      def remove!(*keys)
        keys.each{|key| self.delete(key) }
        self
      end
    
      #non-destructive version
      def remove(*keys)
        self.dup.remove!(*keys)
      end
    end
    
    #in config/initializers/app_environment.rb (or anywhere in config/initializers)
    require 'core_extensions'
    

    我已经设置了这个,以便.remove返回哈希的副本,删除键,同时删除!修改哈希本身 . 这符合ruby惯例 . 例如,从控制台

    >> hash = {:a => 1, :b => 2}
    => {:b=>2, :a=>1}
    >> hash.remove(:a)
    => {:b=>2}
    >> hash
    => {:b=>2, :a=>1}
    >> hash.remove!(:a)
    => {:b=>2}
    >> hash
    => {:b=>2}
    >> hash.remove!(:a, :b)
    => {}
    
  • 1

    如果你想使用纯Ruby(没有Rails),不想创建扩展方法(也许你只需要在一两个地方,并且不想用大量方法污染名称空间)并且不想编辑哈希就位(即,你喜欢像我这样的函数式编程),你可以'选择':

    >> x = {:a => 1, :b => 2, :c => 3}
    => {:a=>1, :b=>2, :c=>3}
    >> x.select{|x| x != :a}
    => {:b=>2, :c=>3}
    >> x.select{|x| ![:a, :b].include?(x)}
    => {:c=>3}
    >> x
    => {:a=>1, :b=>2, :c=>3}
    
  • 637

    Oneliner普通红宝石,它只适用于红宝石> 1.9.x:

    1.9.3p0 :002 > h = {:a => 1, :b => 2}
     => {:a=>1, :b=>2} 
    1.9.3p0 :003 > h.tap { |hs| hs.delete(:a) }
     => {:b=>2}
    

    Tap方法总是返回被调用的对象...

    否则,如果您需要 active_support/core_ext/hash (在每个Rails应用程序中自动需要),您可以根据需要使用以下方法之一:

    ➜  ~  irb
    1.9.3p125 :001 > require 'active_support/core_ext/hash' => true 
    1.9.3p125 :002 > h = {:a => 1, :b => 2, :c => 3}
     => {:a=>1, :b=>2, :c=>3} 
    1.9.3p125 :003 > h.except(:a)
     => {:b=>2, :c=>3} 
    1.9.3p125 :004 > h.slice(:a)
     => {:a=>1}
    

    except使用黑名单方法,因此它删除列为args的所有键,而slice使用白名单方法,因此它删除未列为参数的所有键 . 还存在那些方法( except!slice! )的爆炸版本,它们修改给定的散列,但它们的返回值不同,它们都返回一个散列 . 它表示 slice! 的已删除键以及为 except! 保留的键:

    1.9.3p125 :011 > {:a => 1, :b => 2, :c => 3}.except!(:a)
     => {:b=>2, :c=>3} 
    1.9.3p125 :012 > {:a => 1, :b => 2, :c => 3}.slice!(:a)
     => {:b=>2, :c=>3}
    
  • 15

    有许多方法可以从哈希中删除密钥并在Ruby中获取剩余的哈希值 .

    • .slice =>它将返回选定的键,而不是从原始哈希中删除它们
    2.2.2 :074 > hash = {"one"=>1, "two"=>2, "three"=>3}
     => {"one"=>1, "two"=>2, "three"=>3} 
    2.2.2 :075 > hash.slice("one","two")
     => {"one"=>1, "two"=>2} 
    2.2.2 :076 > hash
     => {"one"=>1, "two"=>2, "three"=>3}
    
    • .delete =>它将从原始哈希中删除所选的键(它只能接受一个键而不能超过一个键)
    2.2.2 :094 > hash = {"one"=>1, "two"=>2, "three"=>3}
     => {"one"=>1, "two"=>2, "three"=>3} 
    2.2.2 :095 > hash.delete("one")
     => 1 
    2.2.2 :096 > hash
     => {"two"=>2, "three"=>3}
    
    • .except =>它将返回剩余的键但不删除原始哈希中的任何内容
    2.2.2 :097 > hash = {"one"=>1, "two"=>2, "three"=>3}
     => {"one"=>1, "two"=>2, "three"=>3} 
    2.2.2 :098 > hash.except("one","two")
     => {"three"=>3} 
    2.2.2 :099 > hash
     => {"one"=>1, "two"=>2, "three"=>3}
    
    • .delete_if =>如果您需要根据值删除密钥 . 它显然会从原始哈希中删除匹配的键
    2.2.2 :115 > hash = {"one"=>1, "two"=>2, "three"=>3, "one_again"=>1}
     => {"one"=>1, "two"=>2, "three"=>3, "one_again"=>1} 
    2.2.2 :116 > value = 1
     => 1 
    2.2.2 :117 > hash.delete_if { |k,v| v == value }
     => {"two"=>2, "three"=>3} 
    2.2.2 :118 > hash
     => {"two"=>2, "three"=>3}
    

    结果基于Ruby 2.2.2 .

  • 0

    Ruby on Rails: Delete multiple hash keys

    hash.delete_if{ |k,| keys_to_delete.include? k }
    
  • 18

    为什么不使用:

    hash.delete(key)
    
  • 47

    您可以使用refinements if you are using Ruby 2代替猴子修补或不必要地包含大型库:

    module HashExtensions
      refine Hash do
        def except!(*candidates)
          candidates.each { |candidate| delete(candidate) }
          self
        end
    
        def except(*candidates)
          dup.remove!(candidates)
        end
      end
    end
    

    您可以使用此功能,而不会影响程序的其他部分,或者必须包含大型外部库 .

    class FabulousCode
      using HashExtensions
    
      def incredible_stuff
        delightful_hash.except(:not_fabulous_key)
      end
    end
    
  • -8

    在纯Ruby中:

    {:a => 1, :b => 2}.tap{|x| x.delete(:a)}   # => {:b=>2}
    
  • 27

    Rails has an except/except! method返回删除了这些键的哈希值 . 如果你在创建自己的版本时没有任何意义 .

    class Hash
      # Returns a hash that includes everything but the given keys.
      #   hash = { a: true, b: false, c: nil}
      #   hash.except(:c) # => { a: true, b: false}
      #   hash # => { a: true, b: false, c: nil}
      #
      # This is useful for limiting a set of parameters to everything but a few known toggles:
      #   @person.update(params[:person].except(:admin))
      def except(*keys)
        dup.except!(*keys)
      end
    
      # Replaces the hash without the given keys.
      #   hash = { a: true, b: false, c: nil}
      #   hash.except!(:c) # => { a: true, b: false}
      #   hash # => { a: true, b: false }
      def except!(*keys)
        keys.each { |key| delete(key) }
        self
      end
    end
    
  • 177

    您可以使用 facets gem中的 except!

    >> require 'facets' # or require 'facets/hash/except'
    => true
    >> {:a => 1, :b => 2}.except(:a)
    => {:b=>2}
    

    原始哈希不会改变 .

    编辑:正如Russel所说,facets存在一些隐藏的问题,并且与ActiveSupport不完全API兼容 . 另一方面,ActiveSupport并不像facet那样完整 . 最后,我使用AS并在代码中包含边缘情况 .

  • 34

    这是一种单行方式,但它不是很易读 . 建议改用两条线 .

    use_remaining_hash_for_something(Proc.new { hash.delete(:key); hash }.call)
    

相关问题