带有perl哈希数组的哈希

问题描述 投票:0回答:2

我知道已经讨论了该主题,但是其他帖子通常具有静态哈希和数组,并且没有显示如何加载哈希和数组。我正在尝试处理音乐库。我有一个带有专辑名称的哈希和一个包含曲目号,歌曲标题和艺术家的哈希数组。这是从iTunes生成的XML文件加载的。

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?
}
arrays perl hash
2个回答
2
投票

此行没有按照您的想法进行:

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

这会将您的哈希解包为键/值对的列表,并将每个散列分别推入数组。您想要的是将对哈希的引用推到数组上。

您可以通过创建哈希的新副本来做到这一点:

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

但是这会带来不必要的哈希副本-这会影响程序的性能。更好的主意是在循环内移动该变量(my %track)的声明(这样,每次循环时您都会得到一个新变量),然后只需将对哈希的引用推送到数组中即可。

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
投票

首先,您希望将哈希作为单个元素推送,因此不是

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

使用

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

在循环中,您可以使用以下方式访问曲目:

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";
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.