Ruby 正在尝试从多个哈希创建深度为3的哈希

Ruby 正在尝试从多个哈希创建深度为3的哈希,ruby,recursion,hash,tree,refactoring,Ruby,Recursion,Hash,Tree,Refactoring,我试图获取一个哈希数组,其中每个哈希的深度都是一,有多个键和值,并试图创建一个包含所有这些数据的新哈希 我的数据: a = {'name' => 200, 'segment' => 'alpha', 'dc' => 'nyc', 'designation' => 'web'} b = {'name' => 201, 'segment' => 'shared', 'dc' => 'nyc', 'designation' => 'generic'}

我试图获取一个哈希数组,其中每个哈希的深度都是一,有多个键和值,并试图创建一个包含所有这些数据的新哈希

我的数据:

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]
    }
  }
}
这是我的代码(至少…它的开头…)

我已经尝试了我的代码的各种变体,我得到了如下结果:

{"alpha"=>"sfc", "shared"=>"sfc"}
{"alpha"=>{"sfc"=>{}}, "shared"=>{"sfc"=>{}}}
{"alpha"=>{"sfc"=>{}}, nil=>{"web"=>[]}, "shared"=>{"sfc"=>{}}}
我需要搜索哪些流行语来解决这个问题

谢谢

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]
          }
        }
      }
有关和,请参阅文档。后者在Ruby v2.4中首次亮相

对于2.4之前的Ruby版本,可以非常轻松地创建方法
Hash#tranform_值

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 }
在Ruby 2.3和2.0中(不带
transform\u值,带
group\u by
):

也许在Ruby 1.8中(没有
groupby
):

编辑

结合Cary的
哈希#转换_值

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
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'}
成员=[a、b、c、d、e、f、g]
puts'==应该在Ruby 1.8中工作=='
类数组#重新打开类数组
def groupedByKey(p_键)
新_h={}
self.each do|el|el必须是散列
key=el[p_key]
除非是新的[key]
然后#密钥不存在,创建一个密钥-值对
new_h[key]=[el]#该值是一个包含整个元素的数组
否则#已经存在一个键和值。。。

new_h[key]抱歉,我不理解预期输出的部分内容。例如:
:alpha->:nyc->:app
。这个三元组没有成员,它来自哪里?那么
null
呢?那
泛型
?@tokland我的道歉,从手机上复制粘贴问题,把事情搞混了。抢手货现在更清楚了吗?什么是
dict
?它是以一个空散列开始的吗?我使用的是1.8(不是我的选择),所以我将通过definally.Egad签出组!当v1.8.7面世时,我们有蒸汽动力机车。我已经编辑了演示如何滚动您自己的
转换_值
,该值应与v.1.8.7一起使用。
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
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
$ 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]}}}
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