我如何使用ruby水平转换我的json数据

问题描述

我希望使用ruby水平转置json数据。我的json数据看起来像这样

    // to download a file we don't want to use window.location.assign because in case of error the broswer
    // will redirect to the error page,instead we create an invisible iframe and set src to it
    function downloadToFile(url) {
        let iframe = document.getElementById('downloadFileIframe');
        if (!iframe) {
            iframe = document.createElement('iframe');
            iframe.setAttribute('id','downloadFileIframe');
            iframe.style.display = 'none';
            document.body.appendChild(iframe);
        }
        iframe.setAttribute('src',url);
    }

我的预期结果是这样的

[
  {
    "ID": "ID001","Type": "Type1","Week": "W1","Count": 1
  },{
    "ID": "ID001","Week": "W2","Count": 2
  },"Type": "Type2","Count": 3
  },"Type": "Type3","Count": 4
  }
]

请让我知道如何使用Ruby做到这一点。这更多是通过将键类型作为分组依据来将值合并到键中的情况。就像我们在sql查询中所做的一样

解决方法

以功能性链接非突变形式优化可读性:

hashes = [
  { ID: "ID001",Type: "Type1",Week: "W1",Count: 1 },{ ID: "ID001",Week: "W2",Count: 2 },Type: "Type2",Count: 3 },Type: "Type3",Count: 4 }
]

grouped = hashes.group_by do |hash|
  hash.slice(:ID,:Type)
end

values_transposed = grouped.transform_values do |grp|
  grp.map { |h| [h[:Week].to_sym,h[:Count]] }.to_h
end

values_transposed.map { |grp,values| grp.merge(values) }
# => [
#  {:ID => "ID001",:Type => "Type1",:W1 => 1,:W2 => 2},#  {:ID => "ID001",:Type => "Type2",:W1 => 2,:W2 => 3},:Type => "Type3",:W1 => 3,:W2 => 4}]
,
arr = [
  {:ID=>"ID001",:Type=>"Type1",:Week=>"W1",:Count=>1},{:ID=>"ID001",:Week=>"W2",:Count=>2},:Type=>"Type2",:Count=>3},:Type=>"Type3",:Count=>4}] 
]
arr.each_with_object({}) do |g,h|
  key = g[:Type]
  (h[key] ||= {}).update(ID: g[:ID],Type: key,g[:Week].to_sym=>g[:Count])
end.values
  #=> [{:ID=>"ID001",:W1=>1,:W2=>2},#    {:ID=>"ID001",:W1=>2,:W2=>3},:W1=>3,:W2=>4}] 

请参见Hash#update(又称merge!)。


步骤如下。

enum = arr.each_with_object({})
  #=> #<Enumerator: [{:ID=>"ID001",...,#     :Count=>2},:Count=>4}]:
  #        each_with_object({})> 

第一个元素由enum生成并传递给块,从而使块变量使用Array Decomposition赋值。

g,h = enum.next
  #=> [{:ID=>"ID001",{}]
g #=> {:ID=>"ID001",:Count=>1}
h #=> {}

然后执行块计算。

key = g[:Type]
  #=> "Type1" 

h[key] ||= {}
h["Type1"] = h["Type1"] || {}
h["Type1"] = nil || {}
h["Type1"] = {}

h #=> { "Type1"=>{} }

h[key].update(ID: g[:ID],g[:Week].to_sym=>g[:Count])
h["Type1"].update(ID: "ID001","W1".to_sym=>1)
{}.update(ID: "ID001",:W1=>1)
  #=> {:ID=>"ID001",:W1=>1} 
h #=> {:ID=>"ID001",:W1=>1}

然后,下一个元素由enum生成并传递到该块。

g,#    {"Type1"=>{:ID=>"ID001",:W1=>1}} 
g #=> {:ID=>"ID001",:Count=>2} 
h #=> {"Type1"=>{:ID=>"ID001",:W1=>1} 

key = g[:Type]
  #=> "Type1" 
h[key] ||= {}
h["Type1"] = h["Type1"] || {}
h["Type1"] = {:ID=>"ID001",:W1=>1} || {}
h["Type1"] = {:ID=>"ID001",:W1=>1}
h #=> {"Type1"=>{:ID=>"ID001",:W1=>1}} (no change)

h[key].update(ID: g[:ID],g[:Week]=>g[:Count])
h["Typt1"].update(ID: g[:ID],g[:Week].to_sym=>g[:Count])
{:ID=>"ID001","W1"=>1}}.update(ID: g[:ID],g[:Week].to_sym=>g[:Count])
  #=> {:ID=>"ID001",:W2=>2} 
h #=> {"Type1"=>{:ID=>"ID001",:W2=>2}} 

对于enum生成并传递到块的其余四个元素,每个元素的计算都是相似的,之后enum返回哈希值:

{"Type1"=>{:ID=>"ID001","Type2"=>{:ID=>"ID001","Type3"=>{:ID=>"ID001",:W2=>4}}

最后一步是使用Hash#values从此哈希中提取值。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...