在Ruby中对哈希数组进行分组和转换

时间:2014-11-04 23:17:09

标签: ruby arrays hash

我有以下哈希:

hash = {"col1"=>["FALSE", "TRUE", "FALSE", "TRUE"],
 "col2"=>["FALSE", "FALSE", "TRUE", "TRUE"],
 "Freq"=>[36146, 2614, 2607, 1692]}

我想通过 col1 对它进行分组,从上面创建一个由两个哈希组成的数组;第一个哈希包含:name => " FALSE"第二个哈希包含:name => " TRUE&#34 ;.

目标是获得以下哈希数组。下面第一个哈希值中的value1和value2对应于col2中归属于FALSE和TRUE的频率。

 [{name=> FALSE, value1 =>  36146, value2 =>  2607 },
 {name=> TRUE, value1 =>  2614, value2 =>  1692 }]

谢谢!

1 个答案:

答案 0 :(得分:0)

我相信这会产生你想要的哈希数组。我已经更改了某些值的名称,以使结果更容易理解。

hash = {"col1"=>["FALSE", "TRUE", "FALSE", "TRUE"],
        "col2"=>["FALSE", "FALSE", "TRUE", "TRUE"],
        "Freq"=>[36146, 2614, 2607, 1692]}

arr = hash["col1"].zip(hash["col2"], hash["Freq"])
  #=> [["FALSE", "FALSE", 36146], ["TRUE", "FALSE", 2614],
  #    ["FALSE", "TRUE",   2607], ["TRUE", "TRUE",  1692]]

arr.each_with_object({}) do |(tf1,tf2,freq),h|
  (h[tf1] ||= {})[:name] = tf1+?1
   h[tf1][tf2+?2] = freq
end.values
  #=> [{:name=>"FALSE1", "FALSE2"=>36146, "TRUE2"=>2607},
  #    {:name=>"TRUE1", "FALSE2"=>2614, "TRUE2"=>1692}]

Enumerable#zip用于生成数组arr,其值如上所示。

enum = arr.each_with_object({})
  #=> #<Enumerator: [["FALSE", "FALSE", 36146], ["TRUE", "FALSE", 2614],
  #   ["FALSE", "TRUE", 2607], ["TRUE", "TRUE", 1692]]:each_with_object({})>

我们可以将枚举器转换为数组,以查看它将传递给它的blocK的值:

enum.to_a
  #=> [[["FALSE", "FALSE", 36146], {}], [["TRUE", "FALSE", 2614], {}],
  #    [["FALSE", "TRUE", 2607],   {}], [["TRUE", "TRUE", 1692],  {}]]

请注意,第一个元素之后的元素中的哈希值(在每个元素中显示为{})在元素传递到块时将是非空的。

第一个数组,

[["FALSE", "FALSE", 36146], {}]

传递到块中,分解并分配给块变量:

tf1 = "FALSE"
tf2 = "FALSE"
freq = 36146
h    = {}

然后我们执行以下操作:

(h[tf1] ||= {})[:name] = tf1+?1
  # (h["FALSE"] ||= {})[:name] = "FALSE"+?1
  # h["FALSE"] = h["FALSE"] || {})[:name] = "FALSE1"
  # h["FALSE"] = nil || {})[:name] = "FALSE1"
  # h["FALSE"] = {})[:name] = "FALSE1"
  # h => {"FALSE"=>{:name=>"FALSE1"}}

h[tf1][tf2+?2] = freq
  # h["FALSE"]["FALSE"] = 36146
  # h => {"FALSE"=>{:name=>"FALSE1", "FALSE"=>36146}} 

enum的每个其他元素传递到块之后,我们有:

h
  #=> {"FALSE"=>{:name=>"FALSE1", "FALSE2"=>36146, "TRUE2"=>2607},
  #    "TRUE"=> {:name=>"TRUE1",  "FALSE2"=>2614,  "TRUE2"=>1692}}

最后一步是提取此哈希的值:

h.values
  #=> [{:name=>"FALSE1", "FALSE2"=>36146, "TRUE2"=>2607},
  #    {:name=>"TRUE1",  "FALSE2"=>2614,  "TRUE2"=>1692}]