嵌套在哈希数组中的元素的位置



我有一个哈希数组,其值是哈希数组:

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_arrayorg_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] }

最新更新