1

我完全把这个问题弄错了。我正在使用 TMDB 的方法:

 my @results = $search->find(id     => 'tt0114694', source => 'imdb_id');

我认为输出是 JSON 格式,所以这让我很困惑,这让我一直在转圈,因为我看错了。

没有意识到下面来自 Dumper 的数据是我必须经过的实际哈希值。

这是我碰壁的地方,所以下面的数据是一个有五个键的哈希。我想要的第五个键包含另一个数组。这是我无法读入的数组。我尝试将其取消引用到哈希中,这就是我失败的地方。

我正在尝试的代码是:

foreach my $narray (@results){
    print $narray->{"movie_results"};
    my @newarray = $narray->{"movie_results"};

    foreach my $otherarray (@newarray){
        my %innerhash = $otherarray;
        print %innerhash;
        print "\n";
    }
  } 

它会打印出一个数组,但我无法读取该数组中的哈希值。

ps 我必须将此输出格式化为代码,否则输出时没有换行符。

   $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'
                                   }
                                 ]
            };
4

3 回答 3

3

你提到你认为你会得到 JSON 输出,但得到了别的东西。该模块为您发出 Web 请求,接收 JSON 响应,并将其转换为 Perl 数据结构。JSON 的 Perl 版本就是您在转储中看到的。

JSON 对象转换为 Perl 哈希,这就是您在数据结构的顶层看到的内容。这是唯一的find回报(稍后会详细介绍):

这是您所拥有的,删除了外foreach循环:

my @newarray = $narray->{"movie_results"};

foreach my $otherarray (@newarray){
    my %innerhash = $otherarray;
    print %innerhash;
    print "\n";
}

in 的值$narray->{"movie_results"}是一个数组引用。所有引用都是标量,而这些标量指向某个数据结构。当您将该标量分配给一个数组时,您最终会得到一个具有相同引用的单元素数组。相反,您可以

my $movie_results = $narray->{"movie_results"};

然后,您取消引用该引用以将其视为一个数组:

foreach my $result ( @$movie_results ){ ... }

或者,我发现v5.24后缀解引用方式更令人愉悦,因为它读起来更好,尤其是当您跳过中间变量时:

foreach my $result ( $movie_results->@* ){ ... }

foreach my $result ( $narray->{"movie_results"}->@* ){ ... }

里面的那个东西$result是另一个哈希引用。

参考和数据结构大约是中级 Perl内容的一半,但也有Perl 数据结构说明书 (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。文档示例显示它返回一个列表(嗯,结果被分配给一个命名数组,这暗示了这一点),但没有find. 它从响应中返回解码后的 JSON。将它分配给一个标量(这将是一个参考)也可以正常工作:

my $result = $tmdb->search->find(
    id     => 'tt0114694',
    source => 'imdb_id'
    );

say Dumper( $results );

返回值来自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}";
    } 
于 2020-12-18T09:02:16.037 回答
2

处理引用时,使用与没有引用相同的语法,但将变量的名称替换为返回引用的块。

%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}";
   }
}

于 2020-12-18T08:08:37.073 回答
0

%newhash{$newkey}应该是$newhash{$newkey}

于 2020-12-18T02:16:21.050 回答