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

Ruby:从散列A到散列B的最快路径,ruby,arrays,sorting,hash,Ruby,Arrays,Sorting,Hash,我是ruby新手,正在寻找一种优雅的方法来对下面的散列进行排序 散列A: 散列B: 基本上,我想要一种简单的方法来迭代此对象,以输出如下表: Metric 1 Metric 2 Metric 3 Bob 10 20 20 Jane 15 15 5 Sally 20 10 10 功能方法假设所有人都有相同的度量键: names = a.values.first.keys b

我是ruby新手,正在寻找一种优雅的方法来对下面的散列进行排序

散列A:

散列B:

基本上,我想要一种简单的方法来迭代此对象,以输出如下表:

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

功能方法假设所有人都有相同的度量键:

names = a.values.first.keys
b = Hash[names.map do |name| 
  [name, Hash[a.map { |metric, values| [metric, values[person]] }]]
end]
[编辑]第二种方法,可能比我第一次尝试更正统。它使用了方面,因此对于那些不熟悉它所处理的新抽象的人来说,它可能看起来有点神秘。但是,如果您检查每个步骤的输出,则很容易:

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] }

功能方法假设所有人都有相同的度量键:

names = a.values.first.keys
b = Hash[names.map do |name| 
  [name, Hash[a.map { |metric, values| [metric, values[person]] }]]
end]
[编辑]第二种方法,可能比我第一次尝试更正统。它使用了方面,因此对于那些不熟悉它所处理的新抽象的人来说,它可能看起来有点神秘。但是,如果您检查每个步骤的输出,则很容易:

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] }
我会更简单地做:

h = {}
a.each do |metric, hash|
  hash.each do |name, value|
    h[name] ||= {}
    h[name][metric] = value
  end
end
我会更简单地做:

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

这里有一个更具功能性的答案。它处理一些名称只出现在某些散列中的情况——比如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

这里有一个更具功能性的答案。它处理一些名称只出现在某些散列中的情况——比如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


a和b中的值不应该匹配吗?谢谢@tokland。更新了我的帖子a和b中的值不应该匹配吗?谢谢@tokland。更新了我的帖子看起来像是sym正在创建的:Bob作为指针,而不仅仅是Bob。。。。别介意我的错误。哦,是的,它是无用的:+1,我不认为在这种情况下,命令式循环比函数式循环更详细、更清晰。不过,要明确的是,每一个都是邪恶的:-@tokland:我应该被冒犯吗@托克兰对我的教诲,每个人有多邪恶?邪恶的记忆明智吗?或者别的什么?它看起来像是在创建:Bob作为指针,而不仅仅是Bob。。。。别介意我的错误。哦,是的,它是无用的:+1,我不认为在这种情况下,命令式循环比函数式循环更详细、更清晰。不过,要明确的是,每一个都是邪恶的:-@tokland:我应该被冒犯吗@托克兰对我的教诲,每个人有多邪恶?邪恶的记忆明智吗?还是别的什么?@apheading:我个人被这句话冒犯了:-更新了第二句话。我没有ree要测试,但1.8.7没有问题,没有使用新的魔法,所以我想ree也可以。我应该补充一点,Enumerablemash来自facets:。诚然,第一段代码有点难看,但罪魁祸首基本上是可怕的非OOP哈希[…]构造函数。太棒了,很遗憾我不能再次+1@一开始:我个人被这句话冒犯了:-更新了第二句话。我没有ree要测试,但1.8.7没有问题,没有使用新的魔法,所以我想ree也可以。我应该补充一点,Enumerablemash来自facets:。诚然,第一段代码有点难看,但罪魁祸首基本上是可怕的非OOP哈希[…]构造函数。太棒了,很遗憾我不能再次+1;