【问题标题】:hash with array of hashes in perlperl中带有哈希数组的哈希
【发布时间】:2020-07-19 18:41:52
【问题描述】:

我知道这个主题已经被覆盖,但其他帖子通常有静态哈希和数组,并且不显示如何加载哈希和数组。 我正在尝试处理音乐库。我有一个带有专辑名称的散列和一个包含曲目编号、歌曲标题和艺术家的散列数组。这是从 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?
}

【问题讨论】:

  • foreach my $trackRec (@trackRecs)?

标签: arrays perl hash


【解决方案1】:

首先你想将哈希作为单个元素推送,所以而不是

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

【讨论】:

    【解决方案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";
    }
    

    【讨论】:

    • 非常感谢。我需要深入研究基础知识。当涉及到简单的结构时,我感到很困惑。再次感谢。
    • @Coltrane58:我推荐Perl Data Structures Cookbook。这就是我多年前掌握这些东西的方式。
    猜你喜欢
    • 2011-04-20
    • 1970-01-01
    • 2012-08-22
    • 1970-01-01
    • 1970-01-01
    • 2015-08-01
    • 2011-07-26
    • 1970-01-01
    相关资源
    最近更新 更多