ха sh с массивом хэшей в perl - PullRequest
0 голосов
/ 07 апреля 2020

Я знаю, что эта топика c была рассмотрена, но в других сообщениях обычно есть хэш и массивы * stati c, и в них не показано, как загружать хэши и массивы. Я пытаюсь обработать библиотеку musi c. У меня есть ха sh с названием альбома и массивом хэшей, которые содержат номер трека, название песни и исполнителя. Он загружается из файла XML, созданного iTunes.

the pared down code follows:

use strict;
use warnings;
use utf8;
use feature 'unicode_strings';
use feature qw( say );
use XML::LibXML qw( );
use URI::Escape;

my $source = "Library.xml";
binmode STDOUT, ":utf8";

# load the xml doc

my $doc = XML::LibXML->load_xml( location => $source )
    or warn $! ? "Error loading XML file: $source $!"
    : "Exit status $?";

    my %hCompilations;
    my %track;

    # extract xml fields
    my @album_nodes = $doc->findnodes('/plist/dict/dict/dict');
    for my $album_idx (0..$#album_nodes) {
        my $album_node = $album_nodes[$album_idx];
        my $trackName = $album_node->findvalue('key[text()="Name"]/following-sibling::*[position()=1]');
        my $artist = $album_node->findvalue('key[text()="Artist"]/following-sibling::*[position()=1]');
        my $album = $album_node->findvalue('key[text()="Album"]/following-sibling::*[position()=1]');
        my $compilation = $album_node->exists('key[text()="Compilation"]');

        # I only want compilations
        if( ! $compilation ) { next; }

        %track = (
                trackName => $trackName,
                trackArtist => $artist,
                );

        push @{$hCompilations{$album}} , %track;    
    }
#loop through each album access the album name field and get what should be the array of tracks
foreach my $albumName ( sort keys %hCompilations ) {
    print "$albumName\n";
    my @trackRecs = @{$hCompilations{$albumName}};

    # how do I loop through the trackrecs?
}

Ответы [ 2 ]

2 голосов
/ 07 апреля 2020

Эта строка не делает то, о чем вы думаете:

push @{$hCompilations{$album}} , %track;

Это развернет ваш ха sh в список пар ключ / значение и приведет к sh каждой из них в отдельности. на ваш массив. То, что вы хотите, это поместить в массив массив sh ссылки на ваш ha sh.

Вы можете сделать это, создав новую копию ha sh:

push @{$hCompilations{$album}} , { %track };

Но для этого требуется лишняя копия ha sh, что повлияет на производительность вашей программы. Лучше было бы переместить объявление этой переменной (my %track) в l oop (чтобы вы каждый раз получали новую переменную вокруг l oop), а затем просто pu sh - ссылку на га sh на ваш массив.

push @{$hCompilations{$album}} , \%track;

У вас уже есть код для получения массива дорожек, поэтому итерация по этому массиву проста.

my @trackRecs = @{$hCompilations{$albumName}};

foreach my $track (@trackRecs) {
   print "$track->{trackName}/$track->{trackArtist}\n";
}

Обратите внимание, что вы не нужен промежуточный массив:

foreach my $track (@{$hCompilations{$albumName}}) {
   print "$track->{trackName}/$track->{trackArtist}\n";
}
2 голосов
/ 07 апреля 2020

Прежде всего вы хотите добавить sh га sh в качестве одного элемента, поэтому вместо

    push @{$hCompilations{$album}} , %track;    

используйте

    push @{$hCompilations{$album}} , {%track};

в l oop Вы можете получить доступ к трекам с помощью:

foreach my $albumName ( sort keys %hCompilations ) {
    print "$albumName\n";
    my @trackRecs = @{$hCompilations{$albumName}};

    # how do I loop through the trackrecs?
    foreach my $track (@trackRecs) {
       print $track->{trackName} . "/" . $track->{trackArtist} . "\n";
    }
}
...