0

另一个线程中,给出了如何访问特定键的具体示例。无论如何,在编写可以访问任意键的子代码时是否有已知的最佳实践?例如,sub get_lat将是一个具体的属性 - 纬度。但请关注更通用的选项,例如sub get_value_by_keys($$$). &get_value_by_keys(bounds,northeast,lat)会回来51.4770228的。

  address_components => [
    {
      long_name => "Blackheath Avenue",
      short_name => "Blackheath Ave",
      types => ["route"],
    },
    {
      long_name => "Greater London",
      short_name => "Gt Lon",
      types => ["administrative_area_level_2", "political"],
    },
    {
      long_name => "United Kingdom",
      short_name => "GB",
      types => ["country", "political"],
    },
    {
      long_name => "SE10 8XJ",
      short_name => "SE10 8XJ",
      types => ["postal_code"],
    },
    {
      long_name => "London", short_name => "London", types => ["postal_town"]
    },
  ],

  formatted_address => "Blackheath Avenue, London SE10 8XJ, UK",   
  geometry => {
    bounds        => {
      northeast => { lat => 51.4770228, lng => 0.0005404 },
      southwest => { lat => 51.4762273, lng => -0.0001147 },
    },
    location      => { lat => 51.4766277, lng => 0.0002212 },
    location_type => "APPROXIMATE",
    viewport      => {
      northeast => { lat => 51.4779740302915, lng => 0.00156183029150203 },
      southwest => { lat => 51.4752760697085, lng => -0.00113613029150203 },
    },
  },

  types => ["route"],

}

任何提示如何解决这个问题以及如何处理这样的结构?

4

2 回答 2

3

要下降到数据结构的任意级别,请从顶部开始。使用变量来保存对当前级别的引用,并在每次找到下一个级别时更新它。如果你一直坚持到最后,这就是你想要的价值:

sub get_value_by_keys {
    my( $current_level, @keys ) = @_;

    foreach my $key ( @keys ) {
        if( eval{ exists $current_level->{$key} } ) {
            print "$key key exists\n";
            $current_level = $current_level->{$key}; # the trick
            }
        else { return }
        }

    return $current_level;
    }

然后,使用您想要的数据结构和键调用它:

get_value_by_keys( $data, qw( geometry bounds northeast lat) );

你根本不需要原型。

于 2013-10-30T21:45:43.290 回答
0

有几个 CPAN 模块可以满足您的需求。例如Data::Diver

use Data::Diver qw(Dive);
print Dive($data, qw(geometry bounds northeast lat)), "\n";

该模块的优点是它还可以处理数据结构中的数组引用。例如,要获取第二个地址组件的 long_name,请使用:

print Dive($data, qw(address_components 1 long_name)), "\n";

其他模块实现了与 XPath 类似的语法 ( Data::DPath, Data::Path),在这里您可以使用类似字符串"//geometry/bounds/northeast/lat"来访问值。

于 2013-10-31T07:47:34.510 回答