我有一个包含哈希和数组的密钥,我想将此值搜索到从Web应用程序获取的结果中。
例如:search_key = {search:[{user:[:first_name,{address:[:state, :city,:zip]}]},:count],search2:[:location]}
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 = {search:[{user:[:first_name,{address:[:state,:city, :zip]}]},:count],search2:[:location]}
这里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可以是任何类型,如数组的哈希,数组的 哈希值。数组数组,哈希哈希哈希
我需要检查所有密钥是否存在,如果其中一个密钥是nil那么它应该返回false
db_data中的db_data [:search] [:user] [:address] [:state]为nil然后该函数应返回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)
递归函数调用无法正常工作。请让我知道我在哪里做错了
答案 0 :(得分: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