Ruby on rails 如何使用ruby水平转换json数据
我希望使用ruby水平转换json数据。我的json数据如下所示Ruby on rails 如何使用ruby水平转换json数据,ruby-on-rails,json,ruby,rubygems,jruby,Ruby On Rails,Json,Ruby,Rubygems,Jruby,我希望使用ruby水平转换json数据。我的json数据如下所示 [ { "ID": "ID001", "Type": "Type1", "Week": "W1", "Count": 1 }, { "ID": "ID001", "Type"
[
{
"ID": "ID001",
"Type": "Type1",
"Week": "W1",
"Count": 1
},
{
"ID": "ID001",
"Type": "Type1",
"Week": "W2",
"Count": 2
},
{
"ID": "ID001",
"Type": "Type2",
"Week": "W1",
"Count": 2
},
{
"ID": "ID001",
"Type": "Type2",
"Week": "W2",
"Count": 3
},
{
"ID": "ID001",
"Type": "Type3",
"Week": "W1",
"Count": 3
},
{
"ID": "ID001",
"Type": "Type3",
"Week": "W2",
"Count": 4
}
]
[
{
"ID": "ID001",
"Type": "Type1",
"W1": 1,
"W2": 2
},
{
"ID": "ID001",
"Type": "Type2",
"W1": 2,
"W2": 3
},
{
"ID": "ID001",
"Type": "Type3",
"W1": 3,
"W2": 4
}
]
我的预期结果是这样的
[
{
"ID": "ID001",
"Type": "Type1",
"Week": "W1",
"Count": 1
},
{
"ID": "ID001",
"Type": "Type1",
"Week": "W2",
"Count": 2
},
{
"ID": "ID001",
"Type": "Type2",
"Week": "W1",
"Count": 2
},
{
"ID": "ID001",
"Type": "Type2",
"Week": "W2",
"Count": 3
},
{
"ID": "ID001",
"Type": "Type3",
"Week": "W1",
"Count": 3
},
{
"ID": "ID001",
"Type": "Type3",
"Week": "W2",
"Count": 4
}
]
[
{
"ID": "ID001",
"Type": "Type1",
"W1": 1,
"W2": 2
},
{
"ID": "ID001",
"Type": "Type2",
"W1": 2,
"W2": 3
},
{
"ID": "ID001",
"Type": "Type3",
"W1": 3,
"W2": 4
}
]
请让我知道我们如何用Ruby做到这一点。这更像是通过引用group by键类型将值合并到键中的情况。就像我们在sql查询中所做的那样,在函数链接非变异样式中优化可读性:
散列=[
{ID:“ID001”,键入:“Type1”,周:“W1”,计数:1},
{ID:“ID001”,键入:“Type1”,周:“W2”,计数:2},
{ID:“ID001”,键入:“Type2”,周:“W1”,计数:2},
{ID:“ID001”,键入:“Type2”,周:“W2”,计数:3},
{ID:“ID001”,键入:“Type3”,周:“W1”,计数:3},
{ID:“ID001”,键入:“Type3”,周:“W2”,计数:4}
]
分组=hashes.group_by do|hash|
hash.slice(:ID,:Type)
终止
值_transposed=grouped.transform_值do | grp|
grp.map{| h |[h[:Week].to_sym,h[:Count]]}.to_h
终止
values_transposed.map{| grp,values | grp.merge(values)}
# => [
#{:ID=>“ID001”,:Type=>“Type1”,:W1=>1,:W2=>2},
#{:ID=>“ID001”,:Type=>“Type2”,:W1=>2,:W2=>3},
#{:ID=>“ID001”,:Type=>“Type3”,:W1=>3,:W2=>4}]
优化功能链接非变异样式的可读性:
散列=[
{ID:“ID001”,键入:“Type1”,周:“W1”,计数:1},
{ID:“ID001”,键入:“Type1”,周:“W2”,计数:2},
{ID:“ID001”,键入:“Type2”,周:“W1”,计数:2},
{ID:“ID001”,键入:“Type2”,周:“W2”,计数:3},
{ID:“ID001”,键入:“Type3”,周:“W1”,计数:3},
{ID:“ID001”,键入:“Type3”,周:“W2”,计数:4}
]
分组=hashes.group_by do|hash|
hash.slice(:ID,:Type)
终止
值_transposed=grouped.transform_值do | grp|
grp.map{| h |[h[:Week].to_sym,h[:Count]]}.to_h
终止
values_transposed.map{| grp,values | grp.merge(values)}
# => [
#{:ID=>“ID001”,:Type=>“Type1”,:W1=>1,:W2=>2},
#{:ID=>“ID001”,:Type=>“Type2”,:W1=>2,:W2=>3},
#{:ID=>“ID001”,:Type=>“Type3”,:W1=>3,:W2=>4}]
请参阅(也称为“合并”)
步骤如下
enum = arr.each_with_object({})
#=> #<Enumerator: [{:ID=>"ID001",..., :Count=>2}, {:ID=>"ID001",...,
# :Count=>2},...,{:ID=>"ID001",..., :Count=>4}]:
# each_with_object({})>
然后执行块计算
key = g[:Type]
#=> "Type1"
h[key] ||= {}
h["Type1"] = h["Type1"] || {}
h["Type1"] = nil || {}
h["Type1"] = {}
h #=> { "Type1"=>{} }
h[key].update(ID: g[:ID], Type: key, g[:Week].to_sym=>g[:Count])
h["Type1"].update(ID: "ID001", Type: "Type1", "W1".to_sym=>1)
{}.update(ID: "ID001", Type: "Type1", :W1=>1)
#=> {:ID=>"ID001", :Type=>"Type1", :W1=>1}
h #=> {:ID=>"ID001", :Type=>"Type1", :W1=>1}
然后,下一个元素由enum
生成并传递给块
g,h = enum.next
#=> [{:ID=>"ID001", :Type=>"Type1", :Week=>"W2", :Count=>2},
# {"Type1"=>{:ID=>"ID001", :Type=>"Type1", :W1=>1}}
g #=> {:ID=>"ID001", :Type=>"Type1", :Week=>"W2", :Count=>2}
h #=> {"Type1"=>{:ID=>"ID001", :Type=>"Type1", :W1=>1}
key = g[:Type]
#=> "Type1"
h[key] ||= {}
h["Type1"] = h["Type1"] || {}
h["Type1"] = {:ID=>"ID001", :Type=>"Type1", :W1=>1} || {}
h["Type1"] = {:ID=>"ID001", :Type=>"Type1", :W1=>1}
h #=> {"Type1"=>{:ID=>"ID001", :Type=>"Type1", :W1=>1}} (no change)
h[key].update(ID: g[:ID], Type: key, g[:Week]=>g[:Count])
h["Typt1"].update(ID: g[:ID], Type: key, g[:Week].to_sym=>g[:Count])
{:ID=>"ID001", :Type=>"Type1", "W1"=>1}}.update(ID: g[:ID], Type: key,
g[:Week].to_sym=>g[:Count])
#=> {:ID=>"ID001", :Type=>"Type1", :W1=>1, :W2=>2}
h #=> {"Type1"=>{:ID=>"ID001", :Type=>"Type1", :W1=>1, :W2=>2}}
对于剩余的四个元素中的每一个元素,enum
生成并传递到块,然后enum
返回散列:
{"Type1"=>{:ID=>"ID001", :Type=>"Type1", :W1=>1, :W2=>2},
"Type2"=>{:ID=>"ID001", :Type=>"Type2", :W1=>2, :W2=>3},
"Type3"=>{:ID=>"ID001", :Type=>"Type3", :W1=>3, :W2=>4}}
最后一步是使用从该散列中提取值
请参阅(也称为“合并”)
步骤如下
enum = arr.each_with_object({})
#=> #<Enumerator: [{:ID=>"ID001",..., :Count=>2}, {:ID=>"ID001",...,
# :Count=>2},...,{:ID=>"ID001",..., :Count=>4}]:
# each_with_object({})>
然后执行块计算
key = g[:Type]
#=> "Type1"
h[key] ||= {}
h["Type1"] = h["Type1"] || {}
h["Type1"] = nil || {}
h["Type1"] = {}
h #=> { "Type1"=>{} }
h[key].update(ID: g[:ID], Type: key, g[:Week].to_sym=>g[:Count])
h["Type1"].update(ID: "ID001", Type: "Type1", "W1".to_sym=>1)
{}.update(ID: "ID001", Type: "Type1", :W1=>1)
#=> {:ID=>"ID001", :Type=>"Type1", :W1=>1}
h #=> {:ID=>"ID001", :Type=>"Type1", :W1=>1}
然后,下一个元素由enum
生成并传递给块
g,h = enum.next
#=> [{:ID=>"ID001", :Type=>"Type1", :Week=>"W2", :Count=>2},
# {"Type1"=>{:ID=>"ID001", :Type=>"Type1", :W1=>1}}
g #=> {:ID=>"ID001", :Type=>"Type1", :Week=>"W2", :Count=>2}
h #=> {"Type1"=>{:ID=>"ID001", :Type=>"Type1", :W1=>1}
key = g[:Type]
#=> "Type1"
h[key] ||= {}
h["Type1"] = h["Type1"] || {}
h["Type1"] = {:ID=>"ID001", :Type=>"Type1", :W1=>1} || {}
h["Type1"] = {:ID=>"ID001", :Type=>"Type1", :W1=>1}
h #=> {"Type1"=>{:ID=>"ID001", :Type=>"Type1", :W1=>1}} (no change)
h[key].update(ID: g[:ID], Type: key, g[:Week]=>g[:Count])
h["Typt1"].update(ID: g[:ID], Type: key, g[:Week].to_sym=>g[:Count])
{:ID=>"ID001", :Type=>"Type1", "W1"=>1}}.update(ID: g[:ID], Type: key,
g[:Week].to_sym=>g[:Count])
#=> {:ID=>"ID001", :Type=>"Type1", :W1=>1, :W2=>2}
h #=> {"Type1"=>{:ID=>"ID001", :Type=>"Type1", :W1=>1, :W2=>2}}
对于剩余的四个元素中的每一个元素,enum
生成并传递到块,然后enum
返回散列:
{"Type1"=>{:ID=>"ID001", :Type=>"Type1", :W1=>1, :W2=>2},
"Type2"=>{:ID=>"ID001", :Type=>"Type2", :W1=>2, :W2=>3},
"Type3"=>{:ID=>"ID001", :Type=>"Type3", :W1=>3, :W2=>4}}
最后一步是从这个散列中提取值。用类似的答案给我一个重拳出击。FWIW,一个简单的基准测试表明,这比
groupby
方法的效率要高一点。@rmlockerd,正如您可能注意到的,这相对有效的原因是,在每一步,一个新的键值对被添加到一个散列中,该散列是h
的keyk
的值;该散列(h[k]
)不会被修改<例如,如果期望的返回值是一个包含散列的数组,例如{:ID=>“ID001”,Type=>“Type1”,w=>{“W1”=>1,“W2”=>2}
,则code>groupby和散列的其他用法在性能上非常相似。在这种情况下,hashh[k]
必须在每一步都进行修改,而不仅仅是添加到中。FWIW,一个简单的基准测试表明,这比groupby
方法的效率要高一点。@rmlockerd,正如您可能注意到的,这相对有效的原因是,在每一步,一个新的键值对被添加到一个散列中,该散列是h
的keyk
的值;该散列(h[k]
)不会被修改<例如,如果期望的返回值是一个包含散列的数组,例如{:ID=>“ID001”,Type=>“Type1”,w=>{“W1”=>1,“W2”=>2}
,则code>groupby和散列的其他用法在性能上非常相似。在这种情况下,hashh[k]
必须在每一步进行修改,而不仅仅是添加到。这看起来很好,也很完美。但我需要的是json数据,而不是哈希。我尝试使用hashes=JSON.parse(JSON)并注释您的hashes变量,我得到了以下错误:“nil:NilClass的undefined method`to_sym'(nomethoderor如果您以JSON字符串开头,那么您将需要与我使用的哈希格式相同的方法(这是您在问题中粘贴的格式),无需任何修改即可使用我的代码。首先,默认情况下,JSON.parse
会创建字符串键,但您可以执行JSON.parse(JSON\u String,Symbol\u names:true)
来获取符号键。这看起来很好,也很完美。但我需要的是JSON数据,而不是哈希。我尝试了哈希=JSON.parse(JSON)在注释hashes变量时,我得到了一个错误:nil:NilClass的“undefined method`to_sym”(nomethoderRor如果您以JSON字符串开头,那么您将需要与我使用的哈希格式相同的方法(这是您在问题中粘贴的),无需任何修改即可使用我的代码。首先,默认情况下,JSON.parse
会创建字符串键,但您可以执行JSON.parse(JSON\u String,Symbol\u names:true)
来获取符号键。