【问题标题】:Deleting a specific element from a nested hash从嵌套哈希中删除特定元素
【发布时间】:2012-06-20 17:48:36
【问题描述】:

我正在尝试使用嵌套哈希。我有一副牌如下所示:

deck_of_cards = {
:hearts => {:two => 2, :three => 3, :four => 4, :five => 5, :six => 6, :seven => 7, :eight => 8, :nine => 9, :ten => 10, :jack => 10, 
            :queen => 10, :king => 10, :ace => 11},
:spades => {:two => 2, :three => 3, :four => 4, :five => 5, :six => 6, :seven => 7, :eight => 8, :nine => 9, :ten => 10, :jack => 10, 
            :queen => 10, :king => 10, :ace => 11},
:clubs => {:two => 2, :three => 3, :four => 4, :five => 5, :six => 6, :seven => 7, :eight => 8, :nine => 9, :ten => 10, :jack => 10, 
            :queen => 10, :king => 10, :ace => 11},
:diamonds => {:two => 2, :three => 3, :four => 4, :five => 5, :six => 6, :seven => 7, :eight => 8, :nine => 9, :ten => 10, :jack => 10, 
            :queen => 10, :king => 10, :ace => 11}
}

我的目标是能够从牌组中取出一张特定的牌,并返回没有该牌的牌组。任何人都可以帮助我如何遍历哈希并删除像两个俱乐部这样的卡吗?

deck_of_cards[:two][:clubs]

此代码可以移除一副牌,但我不知道如何移除特定的牌

deck_of_cards.delete_if {|k, v| k == :spades}

【问题讨论】:

    标签: ruby hash-of-hashes


    【解决方案1】:

    这样做:

    deck_of_cards[:clubs].delete(:two)
    

    【讨论】:

    • 有什么方法可以完全检索新元素?因为这段代码返回了被删除的元素。
    【解决方案2】:

    你可以删除一个元素并返回原始哈希,也可以使用这样的点击函数

    deck_of_cards.tap{|d| 
      d[:hearts].tap{|h| 
        h.delete(:two)
      }
    }
    

    这将返回没有 :two 键的 deck_if_cards 哈希

    你也可以一行完成

        deck_of_cards.tap{|d| d[:hearts].tap{|h| h.delete("two")}}
    

    【讨论】:

    • 我认为你的"two" 应该是:two
    • tap 在某些情况下肯定会有所帮助,但您不需要嵌套它:deck_of_cards.tap{|d| d[:hearts].delete(:two)} 很好
    【解决方案3】:

    使用.tap

    deck_of_cards.tap{ |deck_of_cards| deck_of_cards[:hearts].delete(:two) }
    #=> { 
    #     :hearts=>{:three=>3, :four=>4, :five=>5, :six=>6, :seven=>7, :eight=>8, :nine=>9, :ten=>10, :jack=>10, :queen=>10, :king=>10, :ace=>11}, 
    #     :spades=>{:two=>2, :three=>3, :four=>4, :five=>5, :six=>6, :seven=>7, :eight=>8, :nine=>9, :ten=>10, :jack=>10, :queen=>10, :king=>10, :ace=>11}, 
    #     :clubs=>{:two=>2, :three=>3, :four=>4, :five=>5, :six=>6, :seven=>7, :eight=>8, :nine=>9, :ten=>10, :jack=>10, :queen=>10, :king=>10, :ace=>11}, 
    #     :diamonds=>{:two=>2, :three=>3, :four=>4, :five=>5, :six=>6, :seven=>7, :eight=>8, :nine=>9, :ten=>10, :jack=>10, :queen=>10, :king=>10, :ace=>11} 
    #   }
    

    具有以优雅的方式返回完整哈希而不是仅删除的值的好处。

    【讨论】:

      【解决方案4】:

      你有一个哈希里面有一个哈希,所以你可以这样做:

      deck_of_cards.each {|k,v| v.delete(:two) if k == :clubs}
      

      您使用each 来遍历键和值,并在块内创建一个条件以删除内部哈希上的特定值。

      【讨论】:

      • 被低估的解决方案!
      • 既然可以通过密钥访问子哈希,为什么还要迭代哈希?
      【解决方案5】:

      你必须是这样的:

      def remove_card deck, suit, number
        # do a deep clone
        new_deck = {}
        deck.each { |k, v| new_deck[k] = v.dup }
      
        # remove the card
        new_deck[suit] = new_deck[suit].reject { |k, v| k == number }
      
        new_deck
      end
      

      最好将你的牌组表示为一对数组,如下所示:

      [ [:hearts, :two], [:hearts, :three], ... ]
      

      那你就可以走了:

      def remove_card deck, suit, number
        deck.reject { |(s, n)| n == number and s == suit }
      end
      

      【讨论】:

        【解决方案6】:

        我认为这种方法会为你完成这项工作

        def nested_delete(card:, deck:)
          each do |hash_key, hash_value|
            if hash_key.to_s.eql?(deck)
              self[hash_key].delete(card.to_sym)
            end
          end
          self
        end
        

        假设您想从套牌“红心”中删除卡片“六” 你需要做的就是

        deck_of_cards.nested_delete(card: 'six', deck: 'hearts')
        

        【讨论】:

          【解决方案7】:

          我确实在我的应用程序中将这个问题写为初始化程序,以向 Hash 对象添加一个名为 delete_nested_key 的方法。它删除哈希的嵌套键。您必须将 key_path 作为数组传递(只是要遍历的键列表以转到要删除的键)。

          好像没问题,但是我刚写的,可能有问题。

          class Hash
            module NestedKeyDeletion
              extend ActiveSupport::Concern
          
              included do
                def deleted_nested_key!(key_path)
                  nested_hash = fetch_most_inner_hash(key_path)
                  nested_hash.delete(key_path.last)
          
                  self
                end
          
                private
          
                def fetch_most_inner_hash(key_path)
                  nested_hash = self
          
                  key_path.each_with_index do |key, index|
                    return  nested_hash if index == key_path.size - 1
                    nested_hash = nested_hash.fetch(key)
                  end
                end
              end
            end
          end
          
          Hash.include(Hash::NestedKeyDeletion)
          

          那么你可以这样使用它:

          [1] pry(main)> x = { x: { y: 2} }
          => {:x=>{:y=>2}}
          [2] pry(main)> x.deleted_nested_key!([:x, :y])
          => {:x=>{}}
          [3] pry(main)>
          

          最好的问候, 丹尼尔。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2022-01-14
            • 1970-01-01
            • 1970-01-01
            • 2011-12-13
            • 2013-11-09
            • 1970-01-01
            • 2011-03-27
            • 1970-01-01
            相关资源
            最近更新 更多