【问题标题】:Make hash keys match the order of a hash constant使哈希键与哈希常量的顺序匹配
【发布时间】:2014-12-30 18:07:16
【问题描述】:

我有许多包含相同键但彼此无序的哈希。我需要重新排列每一个以使它们符合正确的顺序:

correct_order = {
  :cat => "cat",
  :dog => "dog",
  :bear => "bear",
  :zebra => "zebra",
  :monkey => "monkey"
}

hash1 = {
  :bear => "bear",
  :cat => "cat"
}

hash2 = {
  :cat => "cat",
  :monkey => "monkey",
  :zebra => "zebra",
  :bear => "bear"
}

hash3 = {
  :dog => "dog",
  :monkey => "monkey",
  :cat => "cat"
}

我将如何比较 hash1、hash2 和 hash3 的键顺序以使每个键匹配其在正确顺序哈希中的位置? hash2 会变成:

hash2 {
  :cat => "cat",
  :bear => "bear",
  :zebra => "zebra",
  :monkey => "monkey"
}

请注意,每个新散列不一定具有所有键。每个散列的大小和顺序都不同。

谢谢

【问题讨论】:

    标签: ruby sorting hash


    【解决方案1】:

    您不能“排序”哈希。

    The doc 说:哈希按照插入相应键的顺序枚举它们的值。

    所以你必须创建一个新的哈希。例如:

    def sort_hash(ordered_keys, hash_to_sort)
      new_hash= {}
      ordered_keys.each do |key|
        new_hash[key]= hash_to_sort[key] if hash_to_sort.has_key?(key)
      end
      new_hash
    end
    
    correct_order = {
      :cat => "cat",
      :dog => "dog",
      :bear => "bear",
      :zebra => "zebra",
      :monkey => "monkey"
    }
    
    hash2 = {
      :cat => "cat",
      :monkey => "monkey",
      :zebra => "zebra",
      :bear => "bear"
    }
    puts sort_hash(correct_order.keys, hash2)
    

    请注意,该函数返回一个新的哈希值。 hash2 没有被修改。

    【讨论】:

      【解决方案2】:

      关于散列元素的顺序有一点需要说明,但我会在向您展示如何做您想做的事情后解决这个问题。这假设您使用的是 Ruby 1.9+,其中保留了键插入的顺序。

      代码

      def reorder(hash, order)
        keys = order & hash.keys
        Hash[keys.zip(hash.values_at(*keys))]
      end
      

      示例

      order = correct_order.keys
        #=> [:cat, :dog, :bear, :zebra, :monkey]
      
      reorder(hash1, order)
        #=> {:cat=>"cat", :bear=>"bear"}
      reorder(hash2, order)
        #=> {:cat=>"cat", :bear=>"bear", :zebra=>"zebra", :monkey=>"monkey"}
      reorder(hash3, order)
        #=> {:cat=>"cat", :dog=>"dog", :monkey=>"monkey"}
      

      说明

      让我们看看代码是如何处理hash1的:

      hash = hash1
        #=> {:bear=>"bear", :cat=>"cat"}
      order 
        #=> [:cat, :dog, :bear, :zebra, :monkey]
      keys = order & hash.keys
        #=> [:cat, :dog, :bear, :zebra, :monkey] & [:bear, :cat]
        #=> [:cat, :bear] 
      arr = keys.zip(hash.values_at(*keys))
        #=> keys.zip({:bear=>"bear", :cat=>"cat"}.values_at(*[:cat, :bear]))
        #=> keys.zip({:bear=>"bear", :cat=>"cat"}.values_at(:cat, :bear))
        #=> keys.zip(["cat", "bear"])
        #=> [[:cat, "cat"], [:bear, "bear"]]
      Hash[arr]
        #=> {:cat=>"cat", :bear=>"bear"}
      

      在 Ruby 1.9+ 中,您可以改为将最后一步编写为:

      arr.to_h
      

      注意Array#& 方法保留了第一个数组的顺序。

      哈希顺序

      在 Ruby 1.9 之前,您不能依赖散列中键值对(我们只说键)的顺序。这在 1.9 中发生了变化。现在您可以确信,当您枚举散列的键时,枚举的顺序将遵循将键添加到散列的顺序。请注意,并非所有 Ruby 主义者都接受这种变化。如果二十年来您一直将哈希视为无序集合,那么这是一个很大的变化。就我个人而言,我喜欢这种变化,并且发现它有很好的用途。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-10-10
        • 2020-01-27
        • 2012-07-22
        • 2022-07-06
        • 2020-12-08
        • 2013-05-19
        • 2013-08-20
        相关资源
        最近更新 更多