如何访问嵌套散列/数组中的元素,给定类似“a.b.0.x”的路径?

我有一个嵌套的散列/阵列,例如:如何访问嵌套散列/数组中的元素,给定类似“a.b.0.x”的路径?

target = { 

:a => {

"b" => [

{

:x => "here"

}

]

}

}

其中散列键是从来没有的数字。给定一串由"."(例如"a.b.0.x")表示的target[:a]["b"][0][:x]之间的索引/键,我如何访问相应的元素?

回答:

path = "a.b.0.x" 

path.split('.').reduce(target) do |acc, val|

case acc

when Array

break nil unless /\A\d+\z/ === val

acc[val.to_i]

when Hash

next acc[val.to_i] if /\A\d+\z/ === val && acc[val.to_i]

acc[val] || acc[val.to_sym]

else break nil

end

end rescue nil

#⇒ "here"

回答:

鉴于这种访问的边缘情况,我建议创建一个新的类来处理这种情况并将输入均匀化为一致的结构。在这种情况下,Hash(可能更边缘的情况下评论欢迎

class DepthAccessor 

class AccessFailure < StandardError

def initialize(val,current=nil,full=nil,depth=nil)

super(

if full && depth

"Failed to find #{val.inspect} for #{current.inspect}:#{current.class} in #{full.inspect} at depth #{depth}"

else

val

end

)

end

end

def initialize(target)

raise ArgumentError, "#{target.inspect}:#{target.class} must respond_to :each_with_object" unless target.respond_to?(:each_with_object)

@target = homogenize(target)

end

def path_search(path,sep: '.',raise_on_fail: true)

split_path = path.split(sep)

split_path.each_with_index.inject(@target) do |acc,(val,idx)|

begin

acc.is_a?(Hash) ? acc[val] : raise

rescue StandardError

if raise_on_fail

raise AccessFailure.new(val,acc,@target,split_path[0..idx].join(sep))

else

nil

end

end

end

end

private

def homogenize(val)

case val

when Array

val.each_with_index.with_object({}) {|(v,idx),obj| obj[idx.to_s] = homogenize(v) }

when Hash

val.each_with_object({}) { |(k,v),obj| obj[k.to_s] = homogenize(v) }

else

val

end

end

end

当你创建一个新的实例中的所有键都转换为Strings和所有Array转换为使用indexkey

Hash ES

然后使用这样

target = { 

:a => {

"b" => [

{

:x => "here"

}

]

}

}

DepthAccessor.new(target).path_search('a.b.0.x')

#=> "here"

DepthAccessor.new(target).path_search('a.b.c.x')

#=> Failed to find "c" for {"0"=>{"x"=>"here"}}:Hash in {"a"=>{"b"=>{"0"=>{"x"=>"here"}}}} at depth a.b.c

Full Example

如果Array小号的预订要求那么这里是另一个例子(有一些额外的功能)Example

以上是 如何访问嵌套散列/数组中的元素,给定类似“a.b.0.x”的路径? 的全部内容, 来源链接: utcz.com/qa/265468.html

回到顶部