2014-10-31 52 views
-1

我有一個包含哈希和數組的鍵,我想將這個值搜索到從Web應用程序獲得的結果。如何在Ruby中深入搜索哈希

例如:SEARCH_KEY = {搜索:[{用戶:[:如first_name,{地址:[:狀態, :城市,:拉鍊]}]},:計數],搜索2:[:位置] }

Search_key可以包含任何鍵和值。這裏的key不是靜態的,它創建動態的,所以它可能是任何。

db_data = { 
     search{ 
      user: { 
      first_name: "Test user", 
      address: { 
       street: "main street", 
       state: nil, 
       city: "Delhi", 
       zip: "12345" 
      }, 
      }, 
      count: 55 
      test: 123 
     }, 
     search2:{ 
      location: "main_data" 
      mobile_no: '9998887776' 
     } 
     } 

我需要獲取檢查數據存在或不存在與以下關鍵基礎:

SEARCH_KEY = {搜索:[{用戶:[:如first_name,{地址:[:狀態,:城市, :拉鍊]}]},:計數],搜索2:[:位置]}

這裏SEARCH_KEY指:

db_data[:search] 
db_data[:search][:user] 
db_data[:search][:user][:first_name] 
db_data[:search][:user][:address] 
db_data[:search][:user][:address][:state] 
db_data[:search][:user][:address][:city] 
db_data[:search][:user][:address][:zip] 
db_data[:search][:count] 
db_data[:search2] 
db_data[:search2][:location] 

**注意:search_key不是靜態的。 search_key的鍵總是會改變,而search_key可能是任何類型,比如散列數組,散列數組。數組的數組,哈希的哈希散列

我需要檢查所有關鍵的存在或不存在,如果其中一個關鍵是零,那麼它應該在DB_DATA DB_DATA返回false

[:搜索] [:user] [:address] [:state]爲零,那麼函數應該返回false。

如果值存在於db_data [:search] [:user] [:address] [:state]中,則函數應該返回true。

[編輯]:

我曾嘗試使用此功能

def data_present?(data, keys) 
    keys.each do |k,v| 
    return false if data[k].nil? 
    if v.is_a? Array 
     v.each do |a| 
     if a.is_a? Hash 
      data_present?(data[k], a) if data[k].is_a?Hash 
      return data[k].each{|r| return data_present?(r, v) } if data[k].is_a?Array 
     else 
      return false if data[k][a].nil? 
     end 
     end 
    end 
    end 
end 

通過

data_present稱爲(DB_DATA,SEARCH_KEY)

遞歸函數調用?工作不正常。請讓我知道我在哪裏做錯了

+2

中指定的帖子的標題寫着「深搜索」一個'Hash'這是不是一種罕見的請求,通常是相當簡單的,通過遞歸來實現。在閱讀實際文章時,我完全喪失了關於如何定義此任務的建議,因爲您在說search_key可以是多個「Enumerable」類型的對象,這使得這更加複雜。你究竟想在這裏實現什麼? – engineersmnky 2014-10-31 15:44:10

+1

這不是一個有效的散列。 – sawa 2014-10-31 15:45:14

+0

@engineersmnky,我嘗試過但不能使用遞歸。你有什麼主意嗎? – 2014-10-31 15:49:38

回答

1

你在尋找類似的東西嗎?

class Hash 
    def flatten_to_key_hierarchy(exclude_nils=false) 
    deep_key_retrieval(exclude_nils).each_with_object({}) do |h,obj| 
     obj.merge!(h) 
    end 
    end 
    def deep_key_retrieval(exclude_nils=false) 
    map do |k,v| 
     if v.is_a?(Hash) 
     Hash[k,v.deep_key_retrieval] 
     else 
     k unless v.nil? && exclude_nils 
     end 
    end.compact 
    end 
end 

這將產生

db_data = { 
     :search=>{ 
     :user=>{ 
      :first_name=>"Test user", 
      :address=>{ 
      :street=>"main street", 
      :state=>nil, 
      :city=>"Delhi", 
      :zip=>"12345"} 
      }, 
      :count=>55, 
      :test=>123 
     }, 
     :search2=>{ 
      :location=>"main_data", 
      :mobile_no=>"9998887776" 
     } 
     } 
db_data.flatten_to_key_hierarchy 
#=>{:search=>[{:user=>[:first_name, {:address=>[:street, :state, :city, :zip]}]}, 
    :count, :test], :search2=>[:location, :mobile_no]} 

就像我說我不知道​​我完全理解你在找什麼,但是這似乎符合您的預期結果。

看到你更新了你的問題。嘗試添加此上述

def data_present?(input={},valid_object={},exclude_nils=false) 
    input = input.flatten_to_key_hierarchy(exclude_nils) 
    validate_against_keys(input,valid_object) 
end 
private 
    def validate_against_keys(input={},valid_object={}) 
    valid_object.each do |k,v| 
     return false unless input.has_key?(k) && input[k].class == v.class 
     if v.is_a?(Hash) 
     validate_against_keys(input[k],v) 
     elsif v.is_a?(Array) 
     return false unless v - input[k] == [] 
     end 
    end 
    true 
    end 

#data_present?將您的原始db_data作爲輸入和已確定的結構valid_object。它會忽略DB_DATA附加鍵只尋找TEST_DATA

test_data = db_data.flatten_to_key_hierarchy 
data_present?(db_data,test_data,true) 
#=> true 
test_data[:search].delete(:test) 
data_present?(db_data,test_data,true) 
#=> true 
test_data[:search] << :something_else 
data_present?(db_data,test_data,true) 
#=> false 
+0

你不需要'obj'或'self.'。 – 2014-10-31 17:20:13

+0

@CarySwoveland是的謝謝你。我已經將它們移除給您,儘管我通常會將其留作澄清之用。特別是'obj'作爲'each_with_object'的返回值,因爲這似乎被錯過了很多。 – engineersmnky 2014-10-31 17:37:51

+0

我是一個最懶惰的人,不是工蜂,所以用一粒鹽來表達我的看法,但我有一個不同的看法:當你添加任何不必要的東西時,你暗示它需要在那裏,這對讀者沒有好處。另一方面,如果你不這樣做(例如'.̶s̶e̶l̶f̶'),並且讀者對這個疏忽感到困惑,他/她很快就會知道並學習他們需要知道的東西。 – 2014-10-31 18:08:20