我有一个哈希数组,其值是哈希数组:
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
的值。
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
。(请注意,孙子 1 和孙子 2 具有相同的: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
. 其中一个宝石是真棒打印,您可以按如下方式调用它:
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"
}
}
}
}
},
...
我认为您应该考虑传递在数据结构中生成当前"位置"所需的键
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] }