Ruby:从散列A到散列B的最快路线

时间:2011-11-01 22:03:27

标签: ruby arrays sorting hash

我是ruby的新手,正在寻找一种优雅的方式来对以下哈希进行排序。

哈希A:

a = { :metric1 => {
          "Bob" =>10,
          "Jane" =>15,
          "Sally" =>20
      },                
      :metric2 => {  
          "Jane" =>15,
          "Bob" =>10,
          "Sally" =>10 
      },         
      :metric3 => {  
          "Bob" =>10,
          "Sally" =>10,
          "Jane" =>5
      }
    }

哈希B:

b = { "Bob" => {
        :metric1 =>10,
        :metric2 =>10,
        :metric3 =>10
      },
      "Jane" => {
        :metric1 =>15,
        :metric2 =>15,
        :metric3 =>5
      },
      "Sally" => {
        :metric1 =>20,
        :metric2 =>10,
        :metric3 =>10
      }
    }

基本上我想要一种简单的方法来迭代这个对象来输出一个像这样的表:

        Metric 1  Metric 2  Metric 3
Bob     10        20        20
Jane    15        15        5
Sally   20        10        10

3 个答案:

答案 0 :(得分:3)

功能方法(假设所有人都有相同的度量标准):

names = a.values.first.keys
b = Hash[names.map do |name| 
  [name, Hash[a.map { |metric, values| [metric, values[person]] }]]
end]

[编辑]第二种方法,可能比我的第一次尝试更正统。它使用Facets(因此对于那些不熟悉它所采用的新抽象的人来说,它看起来有点神秘)。但是,如果检查每个步骤的输出,则很容易:

triplets = a.flat_map { |metric, h| h.map { |name, value| [name, metric, value] } }
pairs_by_name = triplets.map_by { |name, metric, value| [name, [metric, value]] }
b = pairs_by_name.mash { |name, pairs| [name, pairs.to_h] }

答案 1 :(得分:2)

我更简单地做:

h = {}
a.each do |metric, hash|
  hash.each do |name, value|
    h[name] ||= {}
    h[name][metric] = value
  end
end

答案 2 :(得分:0)

这是一个功能更强大的答案。它处理一些名称只出现在某些哈希中的情况 - 假设Sally只出现在:metric3 - 尽管将nils放在结果哈希中

metrics = a.keys
names = a.values.map { |v| v.keys }.flatten.uniq

names.inject({}) do |memo, name|
  memo[name] = metrics.inject({}) do |memo, metric|
    memo[metric] = a[metric][name]
    memo
  end
  memo
end