我正在尝试使用哈希数组,其中每个哈希值都具有多个键,值的深度,并尝试创建包含所有这些数据的新哈希。
我的数据:
a = {'name' => 200, 'segment' => 'alpha', 'dc' => 'nyc', 'designation' => 'web'}
b = {'name' => 201, 'segment' => 'shared', 'dc' => 'nyc', 'designation' => 'generic'}
c = {'name' => 202, 'segment' => 'alpha', 'dc' => 'nyc', 'designation' => 'app'}
d = {'name' => 400, 'segment' => 'alpha', 'dc' => 'sfc', 'designation' => 'web'}
e = {'name' => 401, 'segment' => 'shared', 'dc' => 'sfc', 'designation' => 'web'}
f = {'name' => 402, 'segment' => 'shared', 'dc' => 'sfc', 'designation' => 'app'}
g = {'name' => 403, 'segment' => 'alpha', 'dc' => 'sfc', 'designation' => 'app'}
members = [a,b,c,d,e,f,g]
这是我期待得到的:
{
:alpha => {
:nyc => {
:web => [200],
:app => [202]
},
:sfc => {
:web => [400],
:app => [403],
}
},
:shared => {
:nyc => {
generic => [201]
},
:sfc => {
:app => [402],
:web => [401]
}
}
}
这是我的代码(至少......它的开头......)
members.each do |m|
if m.key? 'segment'
dict[m['segment']] = {} unless dict.key? m['segment']
end
puts m['dc']
if m.key? 'dc'
dict[m['segment']] = m['dc']
#dict[m['segment']['dc']] = m['segment']['dc']# unless dict[m['segment']].key? m['dc']
end
我尝试了各种各样的代码和我得到的结果:
{"alpha"=>"sfc", "shared"=>"sfc"}
{"alpha"=>{"sfc"=>{}}, "shared"=>{"sfc"=>{}}}
{"alpha"=>{"sfc"=>{}}, nil=>{"web"=>[]}, "shared"=>{"sfc"=>{}}}
我需要搜索什么流行语来解决这个问题?
谢谢,
答案 0 :(得分:2)
members.group_by { |g| g['segment'] }.
transform_values { |a| a.group_by { |f| f['dc'] }.
transform_values { |aa| aa.group_by { |h| h['designation'] }.
transform_values { |aaa| aaa.map { |e| e['name'] } } } }
#=> { "alpha"=>{
"nyc"=>{
"web"=>[200],
"app"=>[202]
},
"sfc"=>{
"web"=>[400],
"app"=>[403]
}
},
"shared"=>{
"nyc"=>{
"generic"=>[201]
},
"sfc"=>{
"web"=>[401],
"app"=>[402]
}
}
}
请参阅Enumerble#group_by和Hash#transform_values的文档。后者在Ruby v2.4中首次亮相。
对于2.4之前的Ruby版本,可以很容易地创建方法Hash#tranform_values
。
class Hash
def transform_values
Hash[map { |k,v| [k, yield(v)] }]
end
end
然后,例如,
{ a: 1, b: 3 }.transform_values { |v| 2*v }
#=> { :a=>2, :b=>6 }
答案 1 :(得分:1)
在Ruby 2.3和2.0中(没有transform_values
,group_by
):
a = {'name' => 200, 'segment' => 'alpha', 'dc' => 'nyc', 'designation' => 'web'}
b = {'name' => 201, 'segment' => 'shared', 'dc' => 'nyc', 'designation' => 'generic'}
c = {'name' => 202, 'segment' => 'alpha', 'dc' => 'nyc', 'designation' => 'app'}
d = {'name' => 400, 'segment' => 'alpha', 'dc' => 'sfc', 'designation' => 'web'}
e = {'name' => 401, 'segment' => 'shared', 'dc' => 'sfc', 'designation' => 'web'}
f = {'name' => 402, 'segment' => 'shared', 'dc' => 'sfc', 'designation' => 'app'}
g = {'name' => 403, 'segment' => 'alpha', 'dc' => 'sfc', 'designation' => 'app'}
members = [a,b,c,d,e,f,g]
h1 = members.group_by { | gr | gr['segment'] }
p h1
# in h1 at key k1 put this new value
h1.each { | k1, v1 | h1[k1] = v1.group_by { | gr | gr['dc'] } }
puts
p h1
h1.each { | k1, v1 | v1.each { | k2, v2 | v1[k2] = v2.group_by { | gr | gr['designation'] } } }
puts
p h1
h1.each { | k1, v1 | v1.each { | k2, v2 | v2.each { | k3, v3 | v2[k3] = v3.collect { | el | el['name'] } } } }
puts '--- final result ---'
p h1
也许在Ruby 1.8中(没有group_by
):
a = {'name' => 200, 'segment' => 'alpha', 'dc' => 'nyc', 'designation' => 'web'}
b = {'name' => 201, 'segment' => 'shared', 'dc' => 'nyc', 'designation' => 'generic'}
c = {'name' => 202, 'segment' => 'alpha', 'dc' => 'nyc', 'designation' => 'app'}
d = {'name' => 400, 'segment' => 'alpha', 'dc' => 'sfc', 'designation' => 'web'}
e = {'name' => 401, 'segment' => 'shared', 'dc' => 'sfc', 'designation' => 'web'}
f = {'name' => 402, 'segment' => 'shared', 'dc' => 'sfc', 'designation' => 'app'}
g = {'name' => 403, 'segment' => 'alpha', 'dc' => 'sfc', 'designation' => 'app'}
members = [a,b,c,d,e,f,g]
puts '=== without group_by ==='
class Array # reopen class Array
def groupedByKey(p_key)
new_h = {}
self.each do | el | # el must be a hash
key = el[p_key]
unless new_h[key]
then # the key does not exist, create a key - value pair
new_h[key] = [el] # the value is an array with the whole element
else # a key and value already exist ...
new_h[key] << el # ... push the new value onto the array
end
end
new_h
end
end # class Array
h1 = members.groupedByKey('segment')
p h1
h1.each { | k1, v1 | h1[k1] = v1.groupedByKey('dc') }
puts
p h1
h1.each { | k1, v1 | v1.each { | k2, v2 | v1[k2] = v2.groupedByKey('designation') } }
puts
p h1
h1.each { | k1, v1 | v1.each { | k2, v2 | v2.each { | k3, v3 | v2[k3] = v3.collect { | el | el['name'] } } } }
puts '--- final result ---'
p h1
执行(在2.0中):
$ ruby -w t2.rb
=== without group_by ===
{"alpha"=>[{"name"=>200, "segment"=>"alpha", "dc"=>"nye",
...
--- final result ---
{"alpha"=>{"nyc"=>{"web"=>[200], "app"=>[202]}, "sfc"=>{"web"=>[400], "app"=>[403]}},
"shared"=>{"nyc"=>{"generic"=>[201]}, "sfc"=>{"web"=>[401], "app"=>`[402]}}}
修改强>
结合Cary的Hash#transform_values
:
a = {'name' => 200, 'segment' => 'alpha', 'dc' => 'nyc', 'designation' => 'web'}
b = {'name' => 201, 'segment' => 'shared', 'dc' => 'nyc', 'designation' => 'generic'}
c = {'name' => 202, 'segment' => 'alpha', 'dc' => 'nyc', 'designation' => 'app'}
d = {'name' => 400, 'segment' => 'alpha', 'dc' => 'sfc', 'designation' => 'web'}
e = {'name' => 401, 'segment' => 'shared', 'dc' => 'sfc', 'designation' => 'web'}
f = {'name' => 402, 'segment' => 'shared', 'dc' => 'sfc', 'designation' => 'app'}
g = {'name' => 403, 'segment' => 'alpha', 'dc' => 'sfc', 'designation' => 'app'}
members = [a,b,c,d,e,f,g]
puts '=== should work in Ruby 1.8 ==='
class Array # reopen class Array
def groupedByKey(p_key)
new_h = {}
self.each do | el | # el must be a hash
key = el[p_key]
unless new_h[key]
then # the key does not exist, create a key - value pair
new_h[key] = [el] # the value is an array with the whole element
else # a key and value already exist ...
new_h[key] << el # ... push the new value onto the array
end
end
new_h
end
end # class Array
class Hash
def transformValues
Hash[self.collect { | k, v | [ k, yield(v) ] } ]
end
end
# Step by step
h1 = members.groupedByKey('segment')
puts '--- grouped by segment'
p h1
h2 = h1.transformValues { | v1 | v1.groupedByKey('dc') }
puts '--- grouped by dc'
p h2
h2 = members.groupedByKey('segment').
transformValues { | v1 | v1.groupedByKey('dc').
transformValues { | val | val.groupedByKey('designation') } }
puts '--- grouped by designation'
p h2
# One step.
# Note that the hash returned by each groupedByKey is immediately transformed
# (watch the dot after groupedByKey('xxx')).
h2 = members.groupedByKey('segment').
transformValues { | v1 | v1.groupedByKey('dc').
transformValues { | v2 | v2.groupedByKey('designation').
transformValues { | v3 | v3.collect { | el | el['name'] } } } }
puts '--- final result ---'
p h2