2017-05-04 62 views
0

我有下面的數據結構,並且如果任何位置的遞歸和任意深度的值都是給定的字符串,我試圖返回頂級鍵(lo,eth0或eth1) 。然後在找到第一個字符串實例後終止搜索。如果值遞歸地包含字符串,則Ruby返回頂級散列鍵

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}}} 
+0

請更正您的示例。 (它突然結束。)如果你沒有提供有效的對象,讀者不能測試他們的代碼。當你在它的時候,請給你的散列賦一個變量(例如'h = {「lo」=> ...'),這樣讀者就可以在他們的答案和註釋中引用這個變量而不必定義它。 –

+0

完成。感謝您的評論 –

回答

1

當你想返回頂部父鍵,你可以使用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?這是自提答案返回true有點改進的搜索功能如果找到一個密鑰(或者如果找不到nil)。您可以在Hash#find塊頂級密鑰中使用此函數,如果找到該值,則返回值(添加first返回一個密鑰)。

+0

你能夠解釋一下你最後一行的語法嗎?我在發現聲明之前的部分之後遇到困難。 –

2

既然你有興趣的頂級鍵,你可以做這樣的事情:

hash.find{ |k,v| break k if v.to_s.include? "10.0.128.26" } 
#=> eth0 

使用v.to_s,我們能夠在哈希的字符串表示來搜索,也能夠避免遞歸。

+0

只要把整個事情變成一個字符串,對於這個特殊情況可能會工作得很好。但是我仍然想知道如何正確地搜索像這樣的嵌套哈希值 –

相關問題