Ruby 从动态键和值中获取哈希值 (MIB SNMP)
Ruby hash get from dynamic key and value (MIB SNMP)
我是 ruby 的新手,我有如下哈希数据。
person = {
"PoolName.11.22.33":"pool_a",
"PoolMemberName.11.22.33.11":"member_pool_a1",
"PoolMemberScore.11.22.33.11":0,
"PoolName.11.22.44":"pool_b",
"PoolMemberName.11.22.44.11":"member_pool_b1",
"PoolMemberName.11.22.44.12":"member_pool_b2",
"PoolMemberScore.11.22.44.11":2,
"PoolMemberScore.11.22.44.12":3,
"PoolName.11.22.55":"pool_c",
"PoolMemberName.11.22.55.11":"member_pool_c1",
"PolMemberName.11.22.55.12":"member_pool_c2",
"PoolMemberName.11.22.55.13":"member_pool_c3",
"PoolMemberScore.11.22.55.11":11,
"PoolMemberScore.11.22.55.12":22,
"PoolMemberScore.11.22.55.13":33
}
我能得到如下结果吗:
"pool_a.member_pool_a1" : 0,
"pool_b.member_pool_b1" : 2,
"pool_b.member_pool_b2" : 3,
"pool_c.member_pool_c1" : 11,
"pool_c.member_pool_c2" : 22,
"pool_c.member_pool_c3" : 33
person.
slice_before { |_,v| v.is_a?(String) &&
v.match?(/\Apool_\p{Lower}{,2}\z/) }.
each_with_object({}) do |((_, pool), *rest),h|
pool_str = pool + ".member_pool_"
rest.group_by { |k,_| k[/(?:\.\d+)+\z/] }.
each do |_,((_,s),(_,n))|
(s,n = n,s) if n.is_a?(String)
h[(pool_str + s[/[^_]+\z/]).to_sym] = n
end
end
#=> {:"pool_a.member_pool_a1"=>0,
# :"pool_b.member_pool_b1"=>2,
# :"pool_b.member_pool_b2"=>3,
# :"pool_c.member_pool_c1"=>11,
# :"pool_c.member_pool_c2"=>22,
# :"pool_c.member_pool_c3"=>33}
步骤如下1.
c = person.slice_before { |_,v| v.is_a?(String) &&
v.match?(/\Apool_\p{Lower}{,2}\z/) }
#=> #<Enumerator: #<Enumerator::Generator:0x00005d500f652950>:each>
我们可以通过将此枚举器转换为数组来查看将生成的值。
c.to_a
#=> [[[:"PoolName.11.22.33", "pool_a"],
# [:"PoolMemberName.11.22.33.11", "member_pool_a1"],
# [:"PoolMemberScore.11.22.33.11", 0]],
# [[:"PoolName.11.22.44", "pool_b"],
# [:"PoolMemberName.11.22.44.11", "member_pool_b1"],
# [:"PoolMemberName.11.22.44.12", "member_pool_b2"],
# [:"PoolMemberScore.11.22.44.11", 2],
# [:"PoolMemberScore.11.22.44.12", 3]],
# [[:"PoolName.11.22.55", "pool_c"],
# [:"PoolMemberName.11.22.55.11", "member_pool_c1"],
# [:"PolMemberName.11.22.55.12", "member_pool_c2"],
# [:"PoolMemberName.11.22.55.13", "member_pool_c3"],
# [:"PoolMemberScore.11.22.55.11", 11],
# [:"PoolMemberScore.11.22.55.12", 22],
# [:"PoolMemberScore.11.22.55.13", 33]]]
如上所示,c
生成了 3 个数组,每个数组对应三个池 "a"、"b" 和 "c"。参见 Enumerable#slice_before。继续,
d = c.each_with_object({})
#=> #<Enumerator: #<Enumerator:
# #<Enumerator::Generator:0x00005d500f652950>:each>
# :each_with_object({})>
d
可以被认为是一个 复合枚举数 ,尽管 Ruby 没有这样的概念。参见 Enumerable#each_with_object。第一个元素被生成并传递给块,块变量被分配给该值。
((_, pool), *rest),h = d.next
#=> [[[:"PoolName.11.22.33", "pool_a"],
# [:"PoolMemberName.11.22.33.11", "member_pool_a1"],
# [:"PoolMemberScore.11.22.33.11", 0]], {}]
我们看到块变量现在具有以下值。
pool
#=> "pool_a"
rest
#=> [[:"PoolMemberName.11.22.33.11", "member_pool_a1"],
# [:"PoolMemberScore.11.22.33.11", 0]]
h #=> {}
将数组分解为感兴趣的组件称为 "array decomposition"(搜索 "Array Decomposition")。它也被称为 数组消歧 。这是一个非常强大和有用的技术。请注意 _
是一个有效但有些特殊的局部变量。使用下划线(或以下划线开头的变量名)的主要原因是通知 reader 该变量不会在后续计算中使用。继续,
pool_str = pool + ".member_pool_"
#=> "pool_a.member_pool_"
e = rest.group_by { |k,_| k[/(?:\.\d+)+\z/] }
#=> {".11.22.33.11"=>[
# [:"PoolMemberName.11.22.33.11", "member_pool_a1"],
# [:"PoolMemberScore.11.22.33.11", 0]]}
参见 Enumerable#group_by。继续,
g = e.each
#=> #<Enumerator:
# {".11.22.33.11"=>[
# [:"PoolMemberName.11.22.33.11", "member_pool_a1"],
# [:"PoolMemberScore.11.22.33.11", 0]]}:each>
很多调查员,嗯?同样,生成枚举器的第一个元素并将其传递给块,并为块变量赋值:
p,((q,s),(r,n)) = g.next
#=> [".11.22.33.11",
# [[:"PoolMemberName.11.22.33.11", "member_pool_a1"],
# [:"PoolMemberScore.11.22.33.11", 0]]]
p #=> ".11.22.33.11"
q #=> :"PoolMemberName.11.22.33.11"
s #=> "member_pool_a1"
r #=> :"PoolMemberScore.11.22.33.11"
n #=> 0
p
、q
和 r
不用于块计算。出于这个原因,我对所有三个变量都使用了 _
:
each do |_,((_,s),(_,n))| ...
这个数组分解可能看起来极其复杂,但实际上并非如此。只需将上面一行中括号的位置与上面显示的 g.next
的 return 值中括号的位置进行比较即可。
现在执行块计算。我们无法确定 g.next
的两个元素的顺序是否正确(尽管它们在这里),因此如果需要我们会颠倒它们。
(s,n = n,s) if n.is_a?(String)
#=> nil
s #=> "member_pool_a1"
n #=> 0
i = s[/[^_]+\z/]
#=> "a1"
j = pool_str + i
#=> "pool_a.member_pool_a1"
k = j.to_sym
#=> :"pool_a.member_pool_a1"
h[k] = n
#=> 0
h #=> {:"pool_a.member_pool_a1"=>0}
作为 g.size #=> 1
我们完成了 g
。因此下一步是生成d
(池"b")的下一个元素:
((_, pool), *rest),h = d.next
#=> [[[:"PoolName.11.22.44", "pool_b"],
# [:"PoolMemberName.11.22.44.11", "member_pool_b1"],
# [:"PoolMemberName.11.22.44.12", "member_pool_b2"],
# [:"PoolMemberScore.11.22.44.11", 2],
# [:"PoolMemberScore.11.22.44.12", 3]],
# {:"pool_a.member_pool_a1"=>0}]
pool
#=> "pool_b"
rest
#=> [[:"PoolMemberName.11.22.44.11", "member_pool_b1"],
# [:"PoolMemberName.11.22.44.12", "member_pool_b2"],
# [:"PoolMemberScore.11.22.44.11", 2],
# [:"PoolMemberScore.11.22.44.12", 3]]
h #=> {:"pool_a.member_pool_a1"=>0}
注意块变量 h
是如何更新的。其余计算类似。
1 位经验丰富的 Rubiest:血淋淋的细节警告!
我是 ruby 的新手,我有如下哈希数据。
person = {
"PoolName.11.22.33":"pool_a",
"PoolMemberName.11.22.33.11":"member_pool_a1",
"PoolMemberScore.11.22.33.11":0,
"PoolName.11.22.44":"pool_b",
"PoolMemberName.11.22.44.11":"member_pool_b1",
"PoolMemberName.11.22.44.12":"member_pool_b2",
"PoolMemberScore.11.22.44.11":2,
"PoolMemberScore.11.22.44.12":3,
"PoolName.11.22.55":"pool_c",
"PoolMemberName.11.22.55.11":"member_pool_c1",
"PolMemberName.11.22.55.12":"member_pool_c2",
"PoolMemberName.11.22.55.13":"member_pool_c3",
"PoolMemberScore.11.22.55.11":11,
"PoolMemberScore.11.22.55.12":22,
"PoolMemberScore.11.22.55.13":33
}
我能得到如下结果吗:
"pool_a.member_pool_a1" : 0,
"pool_b.member_pool_b1" : 2,
"pool_b.member_pool_b2" : 3,
"pool_c.member_pool_c1" : 11,
"pool_c.member_pool_c2" : 22,
"pool_c.member_pool_c3" : 33
person.
slice_before { |_,v| v.is_a?(String) &&
v.match?(/\Apool_\p{Lower}{,2}\z/) }.
each_with_object({}) do |((_, pool), *rest),h|
pool_str = pool + ".member_pool_"
rest.group_by { |k,_| k[/(?:\.\d+)+\z/] }.
each do |_,((_,s),(_,n))|
(s,n = n,s) if n.is_a?(String)
h[(pool_str + s[/[^_]+\z/]).to_sym] = n
end
end
#=> {:"pool_a.member_pool_a1"=>0,
# :"pool_b.member_pool_b1"=>2,
# :"pool_b.member_pool_b2"=>3,
# :"pool_c.member_pool_c1"=>11,
# :"pool_c.member_pool_c2"=>22,
# :"pool_c.member_pool_c3"=>33}
步骤如下1.
c = person.slice_before { |_,v| v.is_a?(String) &&
v.match?(/\Apool_\p{Lower}{,2}\z/) }
#=> #<Enumerator: #<Enumerator::Generator:0x00005d500f652950>:each>
我们可以通过将此枚举器转换为数组来查看将生成的值。
c.to_a
#=> [[[:"PoolName.11.22.33", "pool_a"],
# [:"PoolMemberName.11.22.33.11", "member_pool_a1"],
# [:"PoolMemberScore.11.22.33.11", 0]],
# [[:"PoolName.11.22.44", "pool_b"],
# [:"PoolMemberName.11.22.44.11", "member_pool_b1"],
# [:"PoolMemberName.11.22.44.12", "member_pool_b2"],
# [:"PoolMemberScore.11.22.44.11", 2],
# [:"PoolMemberScore.11.22.44.12", 3]],
# [[:"PoolName.11.22.55", "pool_c"],
# [:"PoolMemberName.11.22.55.11", "member_pool_c1"],
# [:"PolMemberName.11.22.55.12", "member_pool_c2"],
# [:"PoolMemberName.11.22.55.13", "member_pool_c3"],
# [:"PoolMemberScore.11.22.55.11", 11],
# [:"PoolMemberScore.11.22.55.12", 22],
# [:"PoolMemberScore.11.22.55.13", 33]]]
如上所示,c
生成了 3 个数组,每个数组对应三个池 "a"、"b" 和 "c"。参见 Enumerable#slice_before。继续,
d = c.each_with_object({})
#=> #<Enumerator: #<Enumerator:
# #<Enumerator::Generator:0x00005d500f652950>:each>
# :each_with_object({})>
d
可以被认为是一个 复合枚举数 ,尽管 Ruby 没有这样的概念。参见 Enumerable#each_with_object。第一个元素被生成并传递给块,块变量被分配给该值。
((_, pool), *rest),h = d.next
#=> [[[:"PoolName.11.22.33", "pool_a"],
# [:"PoolMemberName.11.22.33.11", "member_pool_a1"],
# [:"PoolMemberScore.11.22.33.11", 0]], {}]
我们看到块变量现在具有以下值。
pool
#=> "pool_a"
rest
#=> [[:"PoolMemberName.11.22.33.11", "member_pool_a1"],
# [:"PoolMemberScore.11.22.33.11", 0]]
h #=> {}
将数组分解为感兴趣的组件称为 "array decomposition"(搜索 "Array Decomposition")。它也被称为 数组消歧 。这是一个非常强大和有用的技术。请注意 _
是一个有效但有些特殊的局部变量。使用下划线(或以下划线开头的变量名)的主要原因是通知 reader 该变量不会在后续计算中使用。继续,
pool_str = pool + ".member_pool_"
#=> "pool_a.member_pool_"
e = rest.group_by { |k,_| k[/(?:\.\d+)+\z/] }
#=> {".11.22.33.11"=>[
# [:"PoolMemberName.11.22.33.11", "member_pool_a1"],
# [:"PoolMemberScore.11.22.33.11", 0]]}
参见 Enumerable#group_by。继续,
g = e.each
#=> #<Enumerator:
# {".11.22.33.11"=>[
# [:"PoolMemberName.11.22.33.11", "member_pool_a1"],
# [:"PoolMemberScore.11.22.33.11", 0]]}:each>
很多调查员,嗯?同样,生成枚举器的第一个元素并将其传递给块,并为块变量赋值:
p,((q,s),(r,n)) = g.next
#=> [".11.22.33.11",
# [[:"PoolMemberName.11.22.33.11", "member_pool_a1"],
# [:"PoolMemberScore.11.22.33.11", 0]]]
p #=> ".11.22.33.11"
q #=> :"PoolMemberName.11.22.33.11"
s #=> "member_pool_a1"
r #=> :"PoolMemberScore.11.22.33.11"
n #=> 0
p
、q
和 r
不用于块计算。出于这个原因,我对所有三个变量都使用了 _
:
each do |_,((_,s),(_,n))| ...
这个数组分解可能看起来极其复杂,但实际上并非如此。只需将上面一行中括号的位置与上面显示的 g.next
的 return 值中括号的位置进行比较即可。
现在执行块计算。我们无法确定 g.next
的两个元素的顺序是否正确(尽管它们在这里),因此如果需要我们会颠倒它们。
(s,n = n,s) if n.is_a?(String)
#=> nil
s #=> "member_pool_a1"
n #=> 0
i = s[/[^_]+\z/]
#=> "a1"
j = pool_str + i
#=> "pool_a.member_pool_a1"
k = j.to_sym
#=> :"pool_a.member_pool_a1"
h[k] = n
#=> 0
h #=> {:"pool_a.member_pool_a1"=>0}
作为 g.size #=> 1
我们完成了 g
。因此下一步是生成d
(池"b")的下一个元素:
((_, pool), *rest),h = d.next
#=> [[[:"PoolName.11.22.44", "pool_b"],
# [:"PoolMemberName.11.22.44.11", "member_pool_b1"],
# [:"PoolMemberName.11.22.44.12", "member_pool_b2"],
# [:"PoolMemberScore.11.22.44.11", 2],
# [:"PoolMemberScore.11.22.44.12", 3]],
# {:"pool_a.member_pool_a1"=>0}]
pool
#=> "pool_b"
rest
#=> [[:"PoolMemberName.11.22.44.11", "member_pool_b1"],
# [:"PoolMemberName.11.22.44.12", "member_pool_b2"],
# [:"PoolMemberScore.11.22.44.11", 2],
# [:"PoolMemberScore.11.22.44.12", 3]]
h #=> {:"pool_a.member_pool_a1"=>0}
注意块变量 h
是如何更新的。其余计算类似。
1 位经验丰富的 Rubiest:血淋淋的细节警告!