Ruby return 如果值递归包含字符串,则为顶级哈希键
Ruby return top level hash key if value recursively contains string
我有下面的数据结构,我正在尝试 return 顶级密钥(lo、eth0 或 eth1),如果它的值中任何地方递归和任意深度是给定的字符串。然后在找到字符串的第一个实例后终止搜索。
Find key/value pairs deep inside a hash containing an arbitrary number of nested hashes and arrays
这有点类似于我正在尝试做的事情,但我无法将其映射到我自己的问题
h.find{ |k,v| break k if v.include? "number" }
=> "eth0"
h.find{ |k,v| break k if v.include? "10.0.128.26" }
=> nil
#Should return eth0
我想知道通常如何使用像这样的嵌套数据结构,但我满足于能够在特定的子哈希中专门搜索,在我的例子中是地址。
h = \
{"lo"=>
{"mtu"=>"65536",
"flags"=>["LOOPBACK", "UP", "LOWER_UP"],
"encapsulation"=>"Loopback",
"addresses"=>
{"127.0.0.1"=>
{"family"=>"inet",
"prefixlen"=>"8",
"netmask"=>"255.0.0.0",
"scope"=>"Node"}},
"state"=>"unknown"},
"eth0"=>
{"type"=>"eth",
"number"=>"0",
"mtu"=>"1500",
"flags"=>["BROADCAST", "MULTICAST", "UP", "LOWER_UP"],
"encapsulation"=>"Ethernet",
"addresses"=>
{"00:0C:29:1A:64:6A"=>{"family"=>"lladdr"},
"10.0.128.26"=>
{"family"=>"inet",
"prefixlen"=>"24",
"netmask"=>"255.255.255.0",
"broadcast"=>"10.0.128.255",
"scope"=>"Global"}},
"state"=>"up",
"arp"=>
{"10.0.128.31"=>"00:0c:29:04:12:9a",
"10.0.128.100"=>"00:0c:29:5b:b4:46",
"10.0.128.30"=>"00:0c:29:05:a4:c7",
"10.0.128.18"=>"00:0c:29:6a:3f:75",
"10.0.128.3"=>"0c:c4:7a:c0:31:d1",
"10.0.128.43"=>"00:0c:29:01:eb:6b",
"10.0.128.44"=>"00:09:0f:09:00:03",
"10.0.128.14"=>"00:0c:29:d2:15:80",
"10.0.128.22"=>"00:0c:29:18:99:30"},
"routes"=>
[{"destination"=>"10.0.128.0/24",
"family"=>"inet",
"scope"=>"link",
"proto"=>"kernel",
"src"=>"10.0.128.26"}],
"link_speed"=>10000,
"duplex"=>"Full",
"port"=>"Twisted Pair",
"transceiver"=>"internal",
"auto_negotiation"=>"off",
"mdi_x"=>"Unknown",
"ring_params"=>
{"max_rx"=>4096,
"max_rx_mini"=>0,
"max_rx_jumbo"=>2048,
"max_tx"=>4096,
"current_rx"=>256,
"current_rx_mini"=>0,
"current_rx_jumbo"=>128,
"current_tx"=>512}},
"eth1"=>
{"type"=>"eth",
"number"=>"1",
"mtu"=>"1500",
"flags"=>["BROADCAST", "MULTICAST", "UP", "LOWER_UP"],
"encapsulation"=>"Ethernet",
"addresses"=>
{"00:0C:29:1A:64:74"=>{"family"=>"lladdr"},
"11.11.11.1"=>
{"family"=>"inet",
"prefixlen"=>"24",
"netmask"=>"255.255.255.0",
"broadcast"=>"11.11.11.1",
"scope"=>"Global"}},
"state"=>"up",
"routes"=>
[{"destination"=>"default", "family"=>"inet", "via"=>"11.11.11.1"},
{"destination"=>"11.11.11.1/24",
"family"=>"inet",
"scope"=>"link",
"proto"=>"kernel",
"src"=>"11.11.11.1"}],
"link_speed"=>10000,
"duplex"=>"Full",
"port"=>"Twisted Pair",
"transceiver"=>"internal",
"auto_negotiation"=>"off",
"mdi_x"=>"Unknown",
"ring_params"=>
{"max_rx"=>4096,
"max_rx_mini"=>0,
"max_rx_jumbo"=>2048,
"max_tx"=>4096,
"current_rx"=>256,
"current_rx_mini"=>0,
"current_rx_jumbo"=>128,
"current_tx"=>512}}}
既然你对顶级密钥感兴趣,你可以这样做:
hash.find{ |k,v| break k if v.to_s.include? "10.0.128.26" }
#=> eth0
通过使用v.to_s
,我们可以在哈希的字符串表示中进行搜索,也可以避免递归。
如果您想 return 顶级父键,您可以使用顶级哈希键 mentioned answer 和 find
以简单的方式完成此操作
#return true if find or nil
def deep_key?(obj, key)
if obj.respond_to?(:key?) && obj.key?(key)
true
elsif obj.respond_to?(:each)
r = nil
obj.find{ |*a| r = deep_key?(a.last, key) }
r
end
end
key = '00:0C:29:1A:64:74'
#now you check if the provided key is a top level key or run search
h.key?(key) ? key : h.find { |k, v| deep_key?(v, key) }.first
deep_key?
它是对上述答案的搜索功能的一点修改,即 returns true
如果找到一个键(或者 nil
如果找不到) .您可以在 Hash#find
块内使用此函数 - 顶级键,如果找到,他的值将是结果(添加 first
到 return 只是一个键)。
我有下面的数据结构,我正在尝试 return 顶级密钥(lo、eth0 或 eth1),如果它的值中任何地方递归和任意深度是给定的字符串。然后在找到字符串的第一个实例后终止搜索。
Find key/value pairs deep inside a hash containing an arbitrary number of nested hashes and arrays 这有点类似于我正在尝试做的事情,但我无法将其映射到我自己的问题
h.find{ |k,v| break k if v.include? "number" }
=> "eth0"
h.find{ |k,v| break k if v.include? "10.0.128.26" }
=> nil
#Should return eth0
我想知道通常如何使用像这样的嵌套数据结构,但我满足于能够在特定的子哈希中专门搜索,在我的例子中是地址。
h = \
{"lo"=>
{"mtu"=>"65536",
"flags"=>["LOOPBACK", "UP", "LOWER_UP"],
"encapsulation"=>"Loopback",
"addresses"=>
{"127.0.0.1"=>
{"family"=>"inet",
"prefixlen"=>"8",
"netmask"=>"255.0.0.0",
"scope"=>"Node"}},
"state"=>"unknown"},
"eth0"=>
{"type"=>"eth",
"number"=>"0",
"mtu"=>"1500",
"flags"=>["BROADCAST", "MULTICAST", "UP", "LOWER_UP"],
"encapsulation"=>"Ethernet",
"addresses"=>
{"00:0C:29:1A:64:6A"=>{"family"=>"lladdr"},
"10.0.128.26"=>
{"family"=>"inet",
"prefixlen"=>"24",
"netmask"=>"255.255.255.0",
"broadcast"=>"10.0.128.255",
"scope"=>"Global"}},
"state"=>"up",
"arp"=>
{"10.0.128.31"=>"00:0c:29:04:12:9a",
"10.0.128.100"=>"00:0c:29:5b:b4:46",
"10.0.128.30"=>"00:0c:29:05:a4:c7",
"10.0.128.18"=>"00:0c:29:6a:3f:75",
"10.0.128.3"=>"0c:c4:7a:c0:31:d1",
"10.0.128.43"=>"00:0c:29:01:eb:6b",
"10.0.128.44"=>"00:09:0f:09:00:03",
"10.0.128.14"=>"00:0c:29:d2:15:80",
"10.0.128.22"=>"00:0c:29:18:99:30"},
"routes"=>
[{"destination"=>"10.0.128.0/24",
"family"=>"inet",
"scope"=>"link",
"proto"=>"kernel",
"src"=>"10.0.128.26"}],
"link_speed"=>10000,
"duplex"=>"Full",
"port"=>"Twisted Pair",
"transceiver"=>"internal",
"auto_negotiation"=>"off",
"mdi_x"=>"Unknown",
"ring_params"=>
{"max_rx"=>4096,
"max_rx_mini"=>0,
"max_rx_jumbo"=>2048,
"max_tx"=>4096,
"current_rx"=>256,
"current_rx_mini"=>0,
"current_rx_jumbo"=>128,
"current_tx"=>512}},
"eth1"=>
{"type"=>"eth",
"number"=>"1",
"mtu"=>"1500",
"flags"=>["BROADCAST", "MULTICAST", "UP", "LOWER_UP"],
"encapsulation"=>"Ethernet",
"addresses"=>
{"00:0C:29:1A:64:74"=>{"family"=>"lladdr"},
"11.11.11.1"=>
{"family"=>"inet",
"prefixlen"=>"24",
"netmask"=>"255.255.255.0",
"broadcast"=>"11.11.11.1",
"scope"=>"Global"}},
"state"=>"up",
"routes"=>
[{"destination"=>"default", "family"=>"inet", "via"=>"11.11.11.1"},
{"destination"=>"11.11.11.1/24",
"family"=>"inet",
"scope"=>"link",
"proto"=>"kernel",
"src"=>"11.11.11.1"}],
"link_speed"=>10000,
"duplex"=>"Full",
"port"=>"Twisted Pair",
"transceiver"=>"internal",
"auto_negotiation"=>"off",
"mdi_x"=>"Unknown",
"ring_params"=>
{"max_rx"=>4096,
"max_rx_mini"=>0,
"max_rx_jumbo"=>2048,
"max_tx"=>4096,
"current_rx"=>256,
"current_rx_mini"=>0,
"current_rx_jumbo"=>128,
"current_tx"=>512}}}
既然你对顶级密钥感兴趣,你可以这样做:
hash.find{ |k,v| break k if v.to_s.include? "10.0.128.26" }
#=> eth0
通过使用v.to_s
,我们可以在哈希的字符串表示中进行搜索,也可以避免递归。
如果您想 return 顶级父键,您可以使用顶级哈希键 mentioned answer 和 find
以简单的方式完成此操作
#return true if find or nil
def deep_key?(obj, key)
if obj.respond_to?(:key?) && obj.key?(key)
true
elsif obj.respond_to?(:each)
r = nil
obj.find{ |*a| r = deep_key?(a.last, key) }
r
end
end
key = '00:0C:29:1A:64:74'
#now you check if the provided key is a top level key or run search
h.key?(key) ? key : h.find { |k, v| deep_key?(v, key) }.first
deep_key?
它是对上述答案的搜索功能的一点修改,即 returns true
如果找到一个键(或者 nil
如果找不到) .您可以在 Hash#find
块内使用此函数 - 顶级键,如果找到,他的值将是结果(添加 first
到 return 只是一个键)。