Как расшифровать массив хэшей?

Я совершенно неправильно понял этот вопрос. Использую метод из 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'
                                   }
                                 ]
            };

привет, интересно, возможно, это может быть интересно stackoverflow.com/questions/30759097/…

IronMan 18.12.2020 03:15

Вы спросили: «Как я могу декодировать JSON в удобочитаемый хеш в Perl?», но в вашем вопросе нигде нет JSON. На самом деле у вас уже есть хеш, и ничто не мешает вам его прочитать Так в чем именно заключается ваш вопрос?

ikegami 18.12.2020 03:31

@ikegami Это была моя первая мысль, за исключением того, что возвращаемым значением этого метода является массив, а не скаляр, который может быть ссылкой на хэш.

LuisC329 18.12.2020 03:35

Я имею представление, о чем вы говорите. Я спросил, какой у тебя вопрос?

ikegami 18.12.2020 03:47

Что ж, метод возвращает массив, так что это будет массив хэшей. Я вернусь, чтобы убедиться, что я правильно их перебираю.

LuisC329 18.12.2020 03:57

На самом деле метод find возвращает один элемент. У него просто плохой пример, показывающий, что это присваивается массиву, и нет полезных документов, которые на самом деле говорят вам, что это значит делать.

brian d foy 18.12.2020 10:30

@briandfoy Да, он возвращает только один, но в зависимости от того, что я ищу, он может вернуть больше.

LuisC329 18.12.2020 16:13

Он возвращает декодированный JSON, и вы получите только одну вещь. Это может быть массив JSON, но это одно. Обратите внимание на фактический код, который я откопал для своего ответа.

brian d foy 18.12.2020 16:40
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
8
114
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

%newhash{$newkey} должно быть $newhash{$newkey}.

Я сделал это и получил тот же вывод, но каждая строка заканчивалась на МАССИВ (xxxxxxxxx)

LuisC329 18.12.2020 03:24

@ LuisC329, о чем ты? Значение является ссылкой на массив, так что это совершенно законно.

ikegami 18.12.2020 03:30

@ikegami Я пытаюсь поместить строку JSON в хэш, и, похоже, я попал в избыточный цикл.

LuisC329 18.12.2020 03:32

Какая строка JSON? Вы не показали ни одного JSON.

ikegami 18.12.2020 03:47

@ikegami Я явно неправильно понял свою ситуацию. Раньше я работал с хэшами, но только с теми, которые я сделал, передал и разыменовал. Никогда раньше не получал ни одного метода в этом формате, поэтому я подумал, что это JSON.

LuisC329 18.12.2020 04:52

@ikegami Итак, теперь, когда я понимаю, что имею дело не с JSON, а напрямую с хешем, я продвинулся намного дальше. Но этот пятый ключ, movie_results, значением которого является массив (который, как я полагаю, содержит хэши, вот где я продолжаю бегать по кругу.

LuisC329 18.12.2020 06:00
Ответ принят как подходящий

При работе со ссылкой используйте тот же синтаксис, что и в противном случае, но замените имя переменной блоком, который возвращает ссылку.

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

Видеть

Да, это сработало, и спасибо. Теперь мне нужно выяснить, как уважать другие массивы внутри, но я должен быть в состоянии взять это отсюда. Спасибо.

LuisC329 18.12.2020 16:15

Вы упомянули, что думали, что получите вывод 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}";
    } 

Другие вопросы по теме