[英]Ruby Merge Hash Key Value
I have two hashes: one containing a list of hosts and another with network data. 我有两个哈希值:一个包含主机列表,另一个包含网络数据。 I want to create a third hash that combines the host data with the network data.
我想创建将主机数据与网络数据结合在一起的第三个哈希。
Here's an example of the two hashes: 这是两个哈希的示例:
{
: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"}
}
The merge would be with trust and dmz - replacing the key in the host info with the value of the associated key in the network info. 合并将使用trust和dmz-用网络信息中关联密钥的值替换主机信息中的密钥。 The merged hash would be this:
合并的哈希将是这样的:
{
: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"}}
}
EDIT: I've updatd the host hash to use symbols to make the merge easier. 编辑:我已经更新主机哈希值,以使用符号使合并更加容易。
The idea here is you can convert the initial structure by expanding certain keys, or not expanding others depending on the overall shape of that thing. 这里的想法是,您可以通过扩展某些键来转换初始结构,也可以不扩展其他键,这取决于事物的整体形状。 Here's an example:
这是一个例子:
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", ...
This would be marginally less messy if you had trust: :net80
to keep symbol-symbol matching. 如果您
trust: :net80
来保持符号-符号匹配,那么这将稍微减少混乱。
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" }
}
Here are two approaches that could be used. 这是可以使用的两种方法。
#1 Merge the hash with itself, changing some values #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 Build a hash #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
Try this 尝试这个
hosts.each_value do |hash|
hash[:trust] = nets[hash[:trust]]
hash[:dmz] = nets[hash[:dmz]]
end
NB, this mutates the hosts
data structure. 注意,这会改变
hosts
数据结构。
With Ruby 2.4 long-awaited transform_values
, it's possible to design a solution that would work in many other cases : 使用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"}}}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.