我有两个哈希:一个包含主机列表,另一个包含网络数据。我想创建一个将主机数据与网络数据相结合的第三个哈希。
以下是两个哈希的示例:
{
:myhost1=>{:name=>"hostname1", :trust=>:net80, :dmz=>:net81},
:myhost2=>{:name=>"anotherhost", :trust=>:net80, :dmz=>:net82}
}
{
:net80=>{:range=>"192.168.0.0", :gateway=>"192.168.0.1", :netmask=>"255.255.255.0"},
:net81=>{:range=>"192.168.1.0", :gateway=>"192.168.1.1", :netmask=>"255.255.255.0"},
:net82=>{:range=>"192.168.3.0", :gateway=>"192.168.2.1", :netmask=>"255.255.248.0"}
}
合并将使用trust和dmz - 将主机信息中的密钥替换为网络信息中相关密钥的值。合并的哈希是这样的:
{
:myhost1=>{:name=>"hostname1", :trust=>{:range=>"192.168.0.0", :gateway=>"192.168.0.1", :netmask=>"255.255.255.0"}, :dmz=>{:range=>"192.168.1.0", :gateway=>"192.168.1.1", :netmask=>"255.255.255.0"}},
:myhost2=>{:name=>"anotherhost", :trust=>{:range=>"192.168.0.0", :gateway=>"192.168.0.1", :netmask=>"255.255.255.0"}, :dmz=>{:range=>"192.168.3.0", :gateway=>"192.168.2.1", :netmask=>"255.255.248.0"}}
}
编辑:我已更新主机哈希以使用符号来简化合并。
答案 0 :(得分:2)
这里的想法是你可以通过扩展某些键来转换初始结构,或者根据该事物的整体形状不扩展其他键。这是一个例子:
hosts = {
myhost1: {:name=>"hostname1", :trust=>"net80", :dmz=>"net81"},
myhost2: {:name=>"anotherhost", :trust=>"net80", :dmz=>"net82"}
}
nets = {
net80: {:range=>"192.168.0.0", :gateway=>"192.168.0.1", :netmask=>"255.255.255.0"},
net81: {:range=>"192.168.1.0", :gateway=>"192.168.1.1", :netmask=>"255.255.255.0"},
net82: {:range=>"192.168.3.0", :gateway=>"192.168.2.1", :netmask=>"255.255.248.0"}
}
hosts.collect do |name, entry|
[
name,
entry.map do |key, value|
case (key)
when :name
[ key, value ]
else
[ key, nets[value.to_sym] ]
end
end.to_h
]
end
# => {:myhost1=>{:name=>"hostname1", :trust=>{:range=>"192.168.0.0", ...
如果你trust: :net80
保持符号 - 符号匹配,那么这将稍微不那么混乱。
答案 1 :(得分:2)
hosts = {
:myhost1=>{ :name=>"hostname1", :trust=>:net80, :dmz=>:net81 },
:myhost2=>{ :name=>"anotherhost", :trust=>:net80, :dmz=>:net82 }
}
network = {
:net80=>{ :range=>"192.168.0.0", :gateway=>"192.168.0.1",
:netmask=>"255.255.255.0" },
:net81=>{ :range=>"192.168.1.0", :gateway=>"192.168.1.1",
:netmask=>"255.255.255.0" },
:net82=>{ :range=>"192.168.3.0", :gateway=>"192.168.2.1",
:netmask=>"255.255.248.0" }
}
以下是两种可以使用的方法。
#1将哈希与自身合并,更改某些值
hosts.merge(hosts) { |*,g|
g.merge(trust: network[g[:trust]], dmz: network[g[:dmz]]) }
#=> {
# :myhost1=>{
# :name =>"hostname1",
# :trust=>{ :range=>"192.168.0.0", :gateway=>"192.168.0.1",
# :netmask=>"255.255.255.0" },
# :dmz =>{ :range=>"192.168.1.0", :gateway=>"192.168.1.1",
# :netmask=>"255.255.255.0" }
# },
# :myhost2=>{
# :name =>"anotherhost",
# :trust=>{ :range=>"192.168.0.0", :gateway=>"192.168.0.1",
# :netmask=>"255.255.255.0" },
# :dmz =>{ :range=>"192.168.3.0", :gateway=>"192.168.2.1",
# :netmask=>"255.255.248.0" }
# }
# }
#2构建哈希
hosts.each_with_object({}) { |(host,g), h|
h[host] = { :name =>g[:name],
:trust=>network[g[:trust]],
:dmz =>network[g[:dmz]] } }
#=> same as for #1
答案 2 :(得分:1)
试试这个
hosts.each_value do |hash|
hash[:trust] = nets[hash[:trust]]
hash[:dmz] = nets[hash[:dmz]]
end
注意,这会改变hosts
数据结构。
答案 3 :(得分:0)
使用期待已久的Ruby 2.4 transform_values
,可以设计出适用于许多其他情况的解决方案:
hosts =
{
myhost1: { name: 'hostname1', trust: :net80, dmz: :net81 },
myhost2: { name: 'anotherhost', trust: :net80, dmz: :net82 }
}
networks = {
net80: { range: '192.168.0.0', gateway: '192.168.0.1', netmask: '255.255.255.0' },
net81: { range: '192.168.1.0', gateway: '192.168.1.1', netmask: '255.255.255.0' },
net82: { range: '192.168.3.0', gateway: '192.168.2.1', netmask: '255.255.248.0' }
}
class Hash
#{lost: :key}.translate(key: :clef) #=> {:lost=>:clef}
def translate(dict)
transform_values do |v|
if v.is_a?(Hash)
v.translate(dict)
elsif dict.key?(v)
dict[v]
else
v
end
end
end
end
require 'pp'
pp hosts.translate(networks)
# {:myhost1=>
# {:name=>"hostname1",
# :trust=>
# {:range=>"192.168.0.0",
# :gateway=>"192.168.0.1",
# :netmask=>"255.255.255.0"},
# :dmz=>
# {:range=>"192.168.1.0",
# :gateway=>"192.168.1.1",
# :netmask=>"255.255.255.0"}},
# :myhost2=>
# {:name=>"anotherhost",
# :trust=>
# {:range=>"192.168.0.0",
# :gateway=>"192.168.0.1",
# :netmask=>"255.255.255.0"},
# :dmz=>
# {:range=>"192.168.3.0",
# :gateway=>"192.168.2.1",
# :netmask=>"255.255.248.0"}}}