我有一个哈希数组,其值是哈希数组:
org_array = []
#Create Parents
org_array.push(:org_name => "Parent 1", :org_id => "123ABC", :org_parent_id => nil, :children => [], :status => "created")
org_array.push(:org_name => "Parent 2", :org_id => "456ABC", :org_parent_id => nil, :children => [], :status => "created")
org_array.push(:org_name => "Parent 3", :org_id => "789ABC", :org_parent_id => nil, :children => [], :status => "created")
org_array.push(:org_name => "Parent 4", :org_id => "1011ABC", :org_parent_id => nil, :children => [], :status => "created")
#Create Children
org_array[0][:children].push(:org_name => "Child1", :org_id => "1234ABC", :org_parent_id => "123ABC", :children => [], :status => "created")
org_array[0][:children].push(:org_name => "Child2", :org_id => "5678ABC", :org_parent_id => "123ABC", :children => [], :status => "created")
org_array[0][:children].push(:org_name => "Child3", :org_id => "91011ABC", :org_parent_id => "123ABC", :children => [], :status => "created")
org_array[1][:children].push(:org_name => "Child1", :org_id => "1213ABC", :org_parent_id => "456ABC", :children => [], :status => "created")
org_array[1][:children].push(:org_name => "Child2", :org_id => "1415ABC", :org_parent_id => "456ABC", :children => [], :status => "created")
#Create Grandchildren
org_array[0][:children][0][:children].push(:org_name => "Granchild1", :org_id => "1617ABC", :org_parent_id => "1234ABC", :children => [], :status => "created")
org_array[0][:children][1][:children].push(:org_name => "Granchild2", :org_id => "1617ABC", :org_parent_id => "5678ABC", :children => [], :status => "created")
org_array[0][:children][2][:children].push(:org_name => "Granchild3", :org_id => "1819ABC", :org_parent_id => "91011ABC", :children => [], :status => "created")
org_array[1][:children][0][:children].push(:org_name => "Granchild1", :org_id => "1920ABC", :org_parent_id => "1213ABC", :children => [], :status => "created")
org_array[1][:children][1][:children].push(:org_name => "Granchild2", :org_id => "2122ABC", :org_parent_id => "1415ABC", :children => [], :status => "created")
以下代码返回对象和密钥:
def nested_hash_value(obj, key, value)
if obj.respond_to?(:key?) && obj.key?(key) && obj.has_value?(value)
return obj[key]
elsif obj.respond_to?(:each)#checks to see if its an array
r = nil
obj.find{ |*a|r=nested_hash_value(a.last ,key, value)}
r
end
end
nested_hash_value(org_array, :org_id, "2122ABC")
但我希望它返回对象的位置,例如org_array[1][:children][1][:children][0]
而不是2122ABC
的值。
答案 0 :(得分:1)
def nested_hash_value(arr, key, val, path_arr = [])
return nil if arr.empty?
arr.each_with_index do |h,i|
return path_arr << i if h.key?(key) && h[key] == val
if h.key?(:children) && rv = nested_hash_value(arr[i][:children], \
key, val, path_arr.dup << i << :children)
return rv
end
end
return nil
end
p nested_hash_value(org_array, :org_id, "2122ABC")
# => [1, :children, 1, :children, 0]
p nested_hash_value(org_array, :org_id, "1819ABC")
# => [0, :children, 2, :children, 0]
p nested_hash_value(org_array, :org_id, "789ABC")
# => [2]
p nested_hash_value(org_array, :org_id, "91011ABC")
# => [0, :children, 2]
由于您是Stackoverflow(SO)的新手,我想就您的问题的制定提出一些建议,您可能希望将来适用这些建议:
应用这些原则,您可以从以下内容开始:
org_array =
[{:org_id=>"123ABC", :org_parent_id => nil, :children =>
[{:org_id=>"1234ABC", :org_parent_id=>"123ABC", :children =>
[{:org_id=>"1617ABC", :org_parent_id=>"1234ABC", :children => []}]
},
{:org_id=>"5678ABC", :org_parent_id=>"123ABC", :children =>
[{:org_id=>"1617ABC", :org_parent_id=>"5678ABC", :children => []}]
}
]
},
{:org_id=>"456ABC", :org_parent_id => nil, :children =>
[{:org_id=>"1213ABC", :org_parent_id=>"456ABC", :children =>
[{:org_id=>"1920ABC", :org_parent_id=>"1213ABC", :children => []}]
},
{:org_id=>"1415ABC", :org_parent_id=>"456ABC", :children =>
[{:org_id=>"2122ABC", :org_parent_id=>"1415ABC", :children => []}]
}
]
}
]
如果完全使用水平滚动线条太长而无法显示,请插入线条延续字符。如果没有继续,假装这条线很长:
{:org_id => "1415ABC", :org_parent_id => "456ABC", \
:children =>
您可以考虑在代码中定义orig_arr
,而不是使用所有推送语句(当然,除非它是动态构造的)。
现在让我们考虑更改数组org_array
的结构是否有帮助。考虑到数组索引确实没有用处,你可以考虑使用散列键:org_id
使其成为哈希散列的哈希值。 (注意,Grandchild1和Grandchild2具有相同的:org_id
。这不是问题,因为他们的父母(Child1和Child2)有不同的密钥,但我不知道你是否打算这样做。)
对父ID的反向引用通常不是必需的,因为后者在您需要时可用,或者可以在运行中轻松计算。您可以考虑使用以下哈希值,其中包含org_array
中的所有信息字段:
org_hash =
{"123ABC" => {:org_name => "Parent 1", :status => "created", :children =>
{"1234ABC" => {:org_name => "Child1", :status => "created", :children =>
{"1617ABC" => {:org_name => "Grandchild1", :status => "created"}}},
"5678ABC" => {:org_name => "Child2", :status => "created", :children =>
{"1617ABC" => {:org_name => "Grandchild2", :status => "created"}}}}},
"456ABC" => {:org_name => "Parent 2", :status => "created", :children =>
{"1213ABC" => {:org_name => "Child1", :status => "created", :children =>
{"1920ABC" => {:org_name => "Grandchild1", :status => "created"}}},
"1415ABC" => {:org_name => "Child2", :status => "created", :children =>
{"2122ABC" => {:org_name => "Grandchild2", :status => "created"}}}}}
}
这样定义org_hash
会让您的生活更轻松吗?
顺便说一句,您可能会熟悉一种“漂亮印刷”宝石,它可以对复杂对象(如org_array
和org_hash
)进行格式化。一个这样的宝石是Awesome Print,您可以按如下方式调用:
require 'ap'
ap org_hash
它将显示以下内容(我在父1之后截断):
{
"123ABC" => {
:org_name => "Parent 1",
:status => "created",
:children => {
"1234ABC" => {
:org_name => "Child1",
:status => "created",
:children => {
"1617ABC" => {
:org_name => "Grandchild1",
:status => "created"
}
}
},
"5678ABC" => {
:org_name => "Child2",
:status => "created",
:children => {
"1617ABC" => {
:org_name => "Grandchild2",
:status => "created"
}
}
}
}
},
...
答案 1 :(得分:0)
我认为你应该考虑传递在数据结构中产生当前“位置”所需的密钥
def nested_hash_value(obj, key, value, keychain=[])
keychain << key
if obj.respond_to?(:key?) && obj.key?(key) && obj.has_value?(value)
return keychain
elsif obj.respond_to?(:each) # checks to see if its an array
r = nil
obj.find{ |*a| r=nested_hash_value(a.last ,key, value, keychain) }
r
end
end
nhv_result = nested_hash_value(org_array, :org_id, "2122ABC")
注意:我认为这会输出类似
的内容#=> nhv_result
[1, :children, 1, :children, 0]
但它还没有。我正在进行改进,但这显然是一种可行的方法
然后您的结果是如何再次找到该值的描述符
nhv_result.reduce(org_array) {|acc, key| acc = acc[key] }