简体   繁体   English

将哈希更改为哈希数组

[英]Changing a hash to an array of hash

I want to transform this ruby hash structure into an array of hash. 我想将此红宝石哈希结构转换为哈希数组。 The end structure will be used in the charts api, Thanks in advance 最终结构将在图表API中使用,谢谢

From: 从:

data = 
    {
        ["Transportations", "Not-Approved"] => 350,
        ["Transportations", "Approved"]     => 160,
        ["Communications",  "Not-Approved"] => 300,
        ["Communications","Approved"]       => 80,
        ["Rentals","Not-Approved"]          => 50,
        ["Rentals", "Approved"]             => 145,
        ["Salaries","Not-Approved"]         => 150,
        ["Salaries", "Approved"]            => 310
    }

To: 至:

data = [
    {
        name: "Transportations",
        data: [["Not-Approved", 350], ["Approved", 160]]
    },
    {
        name: "Communications",
        data: [["Not-Approved", 300], ["Approved", 80]]
    },
    {
        name: "Rentals",
        data: [["Not-Approved", 50], ["Approved", 145]]
    },
    {
        name: "Salaries",
        data: [["Not-Approved", 150], ["Approved", 310]]
    }
]

Code

def rearrange(data)
  data.group_by { |k,_| k.first }.map { |name, arr|
    { name: name, data: arr.map { |(_,outcome), val| [outcome, val] } } }
end

Example

data = {
  ["Transportations", "Not-Approved"] => 350,
  ["Transportations", "Approved"]     => 160,
  ["Communications",  "Not-Approved"] => 300,
  ["Communications","Approved"]       => 80,
  ["Rentals","Not-Approved"]          => 50,
  ["Rentals", "Approved"]             => 145,
  ["Salaries","Not-Approved"]         => 150,
  ["Salaries", "Approved"]            => 310
}

rearrange(data)
  #=> [{:name=>"Transportations",
  #     :data=>[["Not-Approved", 350], ["Approved", 160]]},
  #    {:name=>"Communications",
  #     :data=>[["Not-Approved", 300], ["Approved", 80]]},
  #    {:name=>"Rentals",
  #     :data=>[["Not-Approved", 50], ["Approved", 145]]},
  #    {:name=>"Salaries",
  #     :data=>[["Not-Approved", 150], ["Approved", 310]]}
  #   ] 

Explanation 说明

The first step is as follows. 第一步如下。

h = data.group_by { |k,_| k.first }
  #=> { "Transportations"=>[
  #       [["Transportations", "Not-Approved"], 350],
  #       [["Transportations", "Approved"], 160]
  #     ],
  #     "Communications"=>[
  #       [["Communications", "Not-Approved"], 300],
  #       [["Communications", "Approved"], 80]
  #     ],
  #     "Rentals"=>[
  #       [["Rentals", "Not-Approved"], 50],
  #       [["Rentals", "Approved"], 145]
  #     ],
  #     "Salaries"=>[
  #       [["Salaries", "Not-Approved"], 150],
  #       [["Salaries", "Approved"], 310]
  #     ]
  #   } 

Enumerable#group_by 's second block variable holds the value of the key (the key being the first block variable). Enumerable#group_by的第二个块变量保存键的值(该键是第一个块变量)。 For example, when the key is ["Transportations", "Not-Approved"] the value is 350 . 例如,当键为["Transportations", "Not-Approved"] ,值为350 I have assigned the block variable _ (a valid local variable) to the value, mainly to inform the reader that it is not used in the block calculation. 我已将块变量_ (有效的局部变量)分配给该值,主要是为了通知读者该变量未在块计算中使用。

To understand the second step, the mapping of the key-value pair of h , first define 要理解第二步,首先定义h的键-值对

enum = h.map
  #=> #<Enumerator:
  #     {"Transportations"=>[
  #        [["Transportations", "Not-Approved"], 350],
  #        [["Transportations", "Approved"], 160]
  #      ], "Communications"=>[
  #    ...
  #          [["Salaries", "Approved"], 310]]}:map>

The first element of enum is generated and passed to the block, and the block variables are assigned values using parallel assignment . enum的第一个元素生成并传递给块,并且使用并行赋值为块变量分配值。

name, arr = enum.next
  #=> ["Transportations", [
  #      [["Transportations", "Not-Approved"], 350],
  #      [["Transportations", "Approved"], 160]
  #    ]
  #   ] 
name
  #=> "Transportations" 
arr
  #=> [
  #    [["Transportations", "Not-Approved"], 350],
  #    [["Transportations", "Approved"], 160]
  #   ]

map 's block calculation is then performed. 然后执行map的块计算。 First, calculate 首先,计算

a = arr.map { |(_,outcome), val| [outcome, val] }
  #=> [["Not-Approved", 350], ["Approved", 160]]

Then construct the hash for `"Transportation". 然后为“ Transportation”构造哈希。

{ name: name, data: a }
  #=> {:name=>"Transportations",
  #    :data=>[["Not-Approved", 350], ["Approved", 160]]} 

The remaining calculations are similar. 其余计算类似。

Try this, 尝试这个,

h = Hash.new { |h, k| h[k] = { name: k, data: {} }}
data.each { |(name, each), value| h[name][:data][each] = value };
h.values.each { |each| each[:data] = each[:data].to_a }
array = h.values

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM