如何破译哈希数组?
How do I decipher an array of hashes?
这道题我完全答错了。我正在使用 TMDB 中的方法:
my @results = $search->find(id => 'tt0114694', source => 'imdb_id');
我以为输出是 JSON 格式,这让我很困惑,这让我 运行 原地转了一圈,因为我完全看错了。
没有意识到下面来自 Dumper 的数据是我必须经过的实际哈希值。
这是我运行撞墙的地方,所以下面的数据是一个有五个键的散列。第五个键 I want 包含另一个数组。这是我无法读入的数组。我尝试将其取消引用为散列,这就是我失败的地方。
我正在尝试的代码是:
foreach my $narray (@results){
print $narray->{"movie_results"};
my @newarray = $narray->{"movie_results"};
foreach my $otherarray (@newarray){
my %innerhash = $otherarray;
print %innerhash;
print "\n";
}
}
它将打印出一个数组,但我无法读取该数组中的散列。
p.s。我必须将此输出格式化为代码,否则输出时没有换行符。
$VAR1 = {
'tv_season_results' => [],
'tv_results' => [],
'person_results' => [],
'tv_episode_results' => [],
'movie_results' => [
{
'adult' => bless( do{\(my $o = 0)}, 'JSON::PP::Boolean' ),
'vote_average' => '6.8',
'original_title' => 'Tommy Boy',
'vote_count' => 635,
'id' => 11381,
'release_date' => '1995-03-31',
'overview' => 'Party animal Tommy Callahan is a few cans short of a six-pack. But when the family business starts tanking, it\'s up to Tommy and number-cruncher Richard Hayden to save the day.',
'genre_ids' => [
35
],
'title' => 'Tommy Boy',
'video' => $VAR1->{'movie_results'}[0]{'adult'},
'poster_path' => '/g32WbO9nbY5ydpux5hIoiJkLEQi.jpg',
'original_language' => 'en',
'backdrop_path' => '/bZ4diYf7oyDVaRYeWG42Oify2mB.jpg',
'popularity' => '13.945'
}
]
};
%newhash{$newkey}
应该是 $newhash{$newkey}
.
处理引用时,使用与未处理引用相同的语法,但将变量名称替换为 returns 引用的块。
%NAME -> %{ $ref } Or just %$ref
$NAME{...} -> ${ $ref }{...} Although $ref->{...} easier to read.
@NAME -> @{ $ref } Or just @$ref
$NAME[...] -> ${ $ref }[...] Although $ref->[...] easier to read.
让我们给$VAR
一个更好的名字,
my $response = $VAR1;
这意味着你想要
my $results = $response->{movie_results};
for my $result (@$results) {
for my $key (keys(%$result)) {
say "$key: $result->{$key}";
}
}
见
你提到你认为你会得到 JSON 输出,但得到了其他东西。该模块为您发出 Web 请求,收到 JSON 响应,并将其转换为 Perl 数据结构。 JSON 的 Perl 版本就是您在转储中看到的。
一个 JSON 对象变成一个 Perl 散列,所以这就是您在数据结构的顶层看到的。这是一件事情 find
returns(稍后会详细介绍):
这是您所拥有的,删除了外部 foreach
循环:
my @newarray = $narray->{"movie_results"};
foreach my $otherarray (@newarray){
my %innerhash = $otherarray;
print %innerhash;
print "\n";
}
$narray->{"movie_results"}
中的值是一个数组引用。所有引用都是标量,这些标量指向某个数据结构。当您将该标量分配给一个数组时,您最终会得到一个具有相同引用的单元素数组。相反,您可以
my $movie_results = $narray->{"movie_results"};
然后取消引用该引用以将其视为数组:
foreach my $result ( @$movie_results ){ ... }
或者,我觉得 v5.24 postfix dereferencing 方式稍微更令人愉悦,因为它读起来更好,尤其是当您跳过中间变量时:
foreach my $result ( $movie_results->@* ){ ... }
foreach my $result ( $narray->{"movie_results"}->@* ){ ... }
$result
中的那个东西是另一个哈希引用。
引用和数据结构大约是Intermediate Perl, but there is also the Perl data structures cookbook (perldsc)的一半内容。
稍微改进一下你的问题
您可以通过向我们展示您的问题的完整、有效的演示来帮助我们很多。这是我拼凑的:
use v5.10;
use TMDB;
use Data::Dumper;
my $tmdb = TMDB->new( apikey => $ENV{TMDB_API_KEY} );
my @results = $tmdb->search->find(
id => 'tt0114694',
source => 'imdb_id'
);
say Dumper( \@results );
find
的结果存在问题。文档示例显示它 returning 一个列表(好吧,结果被分配给一个命名数组,这意味着),但是 find
没有实际的文档。它 return 是来自响应的解码 JSON。将它分配给一个标量(这将是一个参考)也可以正常工作:
my $result = $tmdb->search->find(
id => 'tt0114694',
source => 'imdb_id'
);
say Dumper( $results );
return 值来自 TMDB::Sesssion::talk()
,也就是这个(或空列表):
return $self->json->decode(
Encode::decode( 'utf-8-strict', $response->{content} ) );
这没什么大不了的。这只是意味着您不需要外部 foreach
。这不是你的责任,因为文档中的示例告诉你完全按照你所做的去做。
现在更好的程序
将所有这些放在一起,这里有一个简单的程序,可以满足您的需要:
use v5.10;
use TMDB;
my $tmdb = TMDB->new( apikey => $ENV{TMDB_API_KEY} );
my $result = $tmdb->search->find(
id => 'tt0114694',
source => 'imdb_id'
);
foreach my $item ( $result->{movie_results}->@* ) {
say "Title: $item->{title}";
}
引用别名
有一项名为 ref aliasing 的实验性功能,可让您将引用分配给命名变量的引用。它是一个别名,因此您可以访问和更改相同的数据,只需使用命名变量即可。当你不喜欢的时候这很方便
use v5.10;
use TMDB;
use experimental qw(refaliasing);
my $tmdb = TMDB->new( apikey => $ENV{TMDB_API_KEY} );
# response is a hash ref, so ref alias to a named hash
\my %result = $tmdb->search->find(
id => 'tt0114694',
source => 'imdb_id'
);
# the part you want is an array ref, so alias that
\my @movie_results = $result{movie_results};
# each item in the array is a hash ref, so alias those too
foreach \my %item ( @movie_results ) {
say "Title: $item{title}";
}
这道题我完全答错了。我正在使用 TMDB 中的方法:
my @results = $search->find(id => 'tt0114694', source => 'imdb_id');
我以为输出是 JSON 格式,这让我很困惑,这让我 运行 原地转了一圈,因为我完全看错了。
没有意识到下面来自 Dumper 的数据是我必须经过的实际哈希值。
这是我运行撞墙的地方,所以下面的数据是一个有五个键的散列。第五个键 I want 包含另一个数组。这是我无法读入的数组。我尝试将其取消引用为散列,这就是我失败的地方。
我正在尝试的代码是:
foreach my $narray (@results){
print $narray->{"movie_results"};
my @newarray = $narray->{"movie_results"};
foreach my $otherarray (@newarray){
my %innerhash = $otherarray;
print %innerhash;
print "\n";
}
}
它将打印出一个数组,但我无法读取该数组中的散列。
p.s。我必须将此输出格式化为代码,否则输出时没有换行符。
$VAR1 = {
'tv_season_results' => [],
'tv_results' => [],
'person_results' => [],
'tv_episode_results' => [],
'movie_results' => [
{
'adult' => bless( do{\(my $o = 0)}, 'JSON::PP::Boolean' ),
'vote_average' => '6.8',
'original_title' => 'Tommy Boy',
'vote_count' => 635,
'id' => 11381,
'release_date' => '1995-03-31',
'overview' => 'Party animal Tommy Callahan is a few cans short of a six-pack. But when the family business starts tanking, it\'s up to Tommy and number-cruncher Richard Hayden to save the day.',
'genre_ids' => [
35
],
'title' => 'Tommy Boy',
'video' => $VAR1->{'movie_results'}[0]{'adult'},
'poster_path' => '/g32WbO9nbY5ydpux5hIoiJkLEQi.jpg',
'original_language' => 'en',
'backdrop_path' => '/bZ4diYf7oyDVaRYeWG42Oify2mB.jpg',
'popularity' => '13.945'
}
]
};
%newhash{$newkey}
应该是 $newhash{$newkey}
.
处理引用时,使用与未处理引用相同的语法,但将变量名称替换为 returns 引用的块。
%NAME -> %{ $ref } Or just %$ref
$NAME{...} -> ${ $ref }{...} Although $ref->{...} easier to read.
@NAME -> @{ $ref } Or just @$ref
$NAME[...] -> ${ $ref }[...] Although $ref->[...] easier to read.
让我们给$VAR
一个更好的名字,
my $response = $VAR1;
这意味着你想要
my $results = $response->{movie_results};
for my $result (@$results) {
for my $key (keys(%$result)) {
say "$key: $result->{$key}";
}
}
见
你提到你认为你会得到 JSON 输出,但得到了其他东西。该模块为您发出 Web 请求,收到 JSON 响应,并将其转换为 Perl 数据结构。 JSON 的 Perl 版本就是您在转储中看到的。
一个 JSON 对象变成一个 Perl 散列,所以这就是您在数据结构的顶层看到的。这是一件事情 find
returns(稍后会详细介绍):
这是您所拥有的,删除了外部 foreach
循环:
my @newarray = $narray->{"movie_results"};
foreach my $otherarray (@newarray){
my %innerhash = $otherarray;
print %innerhash;
print "\n";
}
$narray->{"movie_results"}
中的值是一个数组引用。所有引用都是标量,这些标量指向某个数据结构。当您将该标量分配给一个数组时,您最终会得到一个具有相同引用的单元素数组。相反,您可以
my $movie_results = $narray->{"movie_results"};
然后取消引用该引用以将其视为数组:
foreach my $result ( @$movie_results ){ ... }
或者,我觉得 v5.24 postfix dereferencing 方式稍微更令人愉悦,因为它读起来更好,尤其是当您跳过中间变量时:
foreach my $result ( $movie_results->@* ){ ... }
foreach my $result ( $narray->{"movie_results"}->@* ){ ... }
$result
中的那个东西是另一个哈希引用。
引用和数据结构大约是Intermediate Perl, but there is also the Perl data structures cookbook (perldsc)的一半内容。
稍微改进一下你的问题
您可以通过向我们展示您的问题的完整、有效的演示来帮助我们很多。这是我拼凑的:
use v5.10;
use TMDB;
use Data::Dumper;
my $tmdb = TMDB->new( apikey => $ENV{TMDB_API_KEY} );
my @results = $tmdb->search->find(
id => 'tt0114694',
source => 'imdb_id'
);
say Dumper( \@results );
find
的结果存在问题。文档示例显示它 returning 一个列表(好吧,结果被分配给一个命名数组,这意味着),但是 find
没有实际的文档。它 return 是来自响应的解码 JSON。将它分配给一个标量(这将是一个参考)也可以正常工作:
my $result = $tmdb->search->find(
id => 'tt0114694',
source => 'imdb_id'
);
say Dumper( $results );
return 值来自 TMDB::Sesssion::talk()
,也就是这个(或空列表):
return $self->json->decode(
Encode::decode( 'utf-8-strict', $response->{content} ) );
这没什么大不了的。这只是意味着您不需要外部 foreach
。这不是你的责任,因为文档中的示例告诉你完全按照你所做的去做。
现在更好的程序
将所有这些放在一起,这里有一个简单的程序,可以满足您的需要:
use v5.10;
use TMDB;
my $tmdb = TMDB->new( apikey => $ENV{TMDB_API_KEY} );
my $result = $tmdb->search->find(
id => 'tt0114694',
source => 'imdb_id'
);
foreach my $item ( $result->{movie_results}->@* ) {
say "Title: $item->{title}";
}
引用别名
有一项名为 ref aliasing 的实验性功能,可让您将引用分配给命名变量的引用。它是一个别名,因此您可以访问和更改相同的数据,只需使用命名变量即可。当你不喜欢的时候这很方便
use v5.10;
use TMDB;
use experimental qw(refaliasing);
my $tmdb = TMDB->new( apikey => $ENV{TMDB_API_KEY} );
# response is a hash ref, so ref alias to a named hash
\my %result = $tmdb->search->find(
id => 'tt0114694',
source => 'imdb_id'
);
# the part you want is an array ref, so alias that
\my @movie_results = $result{movie_results};
# each item in the array is a hash ref, so alias those too
foreach \my %item ( @movie_results ) {
say "Title: $item{title}";
}