Я совершенно неправильно понял этот вопрос. Использую метод из 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";
}
}
Он распечатает массив, но я не могу прочитать хэш в этом массиве.
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'
}
]
};
Вы спросили: «Как я могу декодировать JSON в удобочитаемый хеш в Perl?», но в вашем вопросе нигде нет JSON. На самом деле у вас уже есть хеш, и ничто не мешает вам его прочитать Так в чем именно заключается ваш вопрос?
@ikegami Это была моя первая мысль, за исключением того, что возвращаемым значением этого метода является массив, а не скаляр, который может быть ссылкой на хэш.
Я имею представление, о чем вы говорите. Я спросил, какой у тебя вопрос?
Что ж, метод возвращает массив, так что это будет массив хэшей. Я вернусь, чтобы убедиться, что я правильно их перебираю.
На самом деле метод find
возвращает один элемент. У него просто плохой пример, показывающий, что это присваивается массиву, и нет полезных документов, которые на самом деле говорят вам, что это значит делать.
@briandfoy Да, он возвращает только один, но в зависимости от того, что я ищу, он может вернуть больше.
Он возвращает декодированный JSON, и вы получите только одну вещь. Это может быть массив JSON, но это одно. Обратите внимание на фактический код, который я откопал для своего ответа.
%newhash{$newkey}
должно быть $newhash{$newkey}
.
Я сделал это и получил тот же вывод, но каждая строка заканчивалась на МАССИВ (xxxxxxxxx)
@ LuisC329, о чем ты? Значение является ссылкой на массив, так что это совершенно законно.
@ikegami Я пытаюсь поместить строку JSON в хэш, и, похоже, я попал в избыточный цикл.
Какая строка JSON? Вы не показали ни одного JSON.
@ikegami Я явно неправильно понял свою ситуацию. Раньше я работал с хэшами, но только с теми, которые я сделал, передал и разыменовал. Никогда раньше не получал ни одного метода в этом формате, поэтому я подумал, что это JSON.
@ikegami Итак, теперь, когда я понимаю, что имею дело не с JSON, а напрямую с хешем, я продвинулся намного дальше. Но этот пятый ключ, movie_results, значением которого является массив (который, как я полагаю, содержит хэши, вот где я продолжаю бегать по кругу.
При работе со ссылкой используйте тот же синтаксис, что и в противном случае, но замените имя переменной блоком, который возвращает ссылку.
%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, но получили что-то другое. Модуль сделал для вас веб-запрос, получил ответ JSON и преобразовал его в структуру данных Perl. Эта Perl-версия JSON — это то, что вы видите в дампе.
Объект JSON превращается в хеш Perl, вот что вы видите на верхнем уровне структуры данных. Это единственное, что возвращает find
(подробнее об этом чуть позже):
Вот что у вас получилось, удалив внешнюю петлю 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 постфиксного разыменования, который мне кажется немного более приятным, поскольку он лучше читается, особенно когда вы пропускаете промежуточную переменную:
foreach my $result ( $movie_results->@* ){ ... }
foreach my $result ( $narray->{"movie_results"}->@* ){ ... }
Эта штука в $result
— еще одна ссылка на хэш.
Ссылки и структуры данных составляют примерно половину содержания Intermediate 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}";
}
привет, интересно, возможно, это может быть интересно stackoverflow.com/questions/30759097/…