【问题标题】:printing out a multilevel hash perl 5打印出多级哈希 perl 5
【发布时间】:2014-10-18 14:35:26
【问题描述】:

我必须理解这个脚本,而不是做大的改变和侮辱制作它的人。我无法更改哈希,即使将数据加载到数组然后拆分很容易。写这篇文章的人(我的老板)喜欢他的多级哈希。我必须打印出 %extend_hash 多级哈希 - 我不明白如何到达最后一级。我需要将其打印到销售人员可以阅读的 CSV 文件中。 它看起来像6个级别。 我必须对散列、散列、散列等的键进行排序。

#!/scripts/perl/bin/perl
use strict;
use warnings;
use DBI;

my $dbUser = 'foo_01';
my $dbPass = 'foo_01';
my $dbSid  = 'foo.WORLD';
my $dbh =  DBI->connect("dbi:Oracle:$dbSid","$dbUser","$dbPass") or die( "Couldn't connect: $!" );

#sub read_extend

my %extend_hash = ();
my $query = "select level_id,e_risk_symbol,e_exch_dest,penny,specialist from etds_extend";
if(!$dbh) {
    print "Error connecting to DataBase; $DBI::errstr\n";
        }
my $cur_msg = $dbh->prepare($query) or die "\n\nCould not prepare statement: ".$dbh->errstr;
$cur_msg->execute();
while (my @row=$cur_msg->fetchrow_array) {
    $extend_hash{$row[0]}{$row[1]}{$row[2]}{'penny'}=$row[3];
    $extend_hash{$row[0]}{$row[1]}{$row[2]}{'specialist'}=$row[4];
}

for my $what_row0 (sort keys %extend_hash) {
    for my $what_row1 (sort keys %{$extend_hash {$what_row0} }) {
        for my $what_row2 (sort keys ..... I am lost.

我不知道如何将 %extend_hash 打印到最低级别 我试图让它以逗号分隔,能够被输入电子邮件并被销售人员阅读。

6,ACI,ARCX,specialist,1
6,ACI,ARCX,penny,0
6,MCHP,ARCX,specialist,1,
6,MCHP,ARCX,penny,0
6,BC,AMXO,specialist,1
6,BC,AMXO,penny,0
6,WM,XISX,specialist,1
6,WM,XISX,penny,0
6,PK,AMXO,specialist,1
6,PK,AMXO,penny,0
6,SPLS,XISX,specialist,1
6,SPLS,XISX,penny,0

如果我使用 Data::Dumper,我会觉得这很棒,但销售/营销人员会感到困惑。他们将无法看到 ARCX penny0 与“6”组的关系。我不认为他们能够在精神上通过数据::转储

$VAR1 = {
          '6' => {
                    'IACI' => {
                               'ARCX' => {
                                            'specialist' => '1',
                                            'penny' => '0'
                                          }
                             },
                   'MCHP' => {
                                'ARCX' => {
                                           'specialist' => '1',
                                            'penny' => '0'
                                         }
                             },
                    'BC' => {
                             'AMXO' => {
                                         'specialist' => '1',
                                         'penny' => '0'
                                       }
                            },
                    'WM' => {
                             'XISX' => {
                                         'specialist' => '1',
                                         'penny' => '0'
                                       }
                            },
                   'PKD' => {
                              'AMXO' => {
                                           'specialist' => '1',
                                           'penny' => '0'
                                         }
                            },
                    'SPLS' => {
                               'XISX' => {
                                           'specialist' => '1',
                                           'penny' => '0'
                                 }
                    }
          } 
};

更新 - 了不起的工作 I_alarmed_alien - 这应该是一个很好的 stackoverflow 参考(我的 cmets 已禁用)

for my $level_1 (sort keys %extend_hash) {
     for my $level_2 (sort keys %{$extend_hash{$level_1} }) {
        for my $level_3 (sort keys %{$extend_hash{$level_1}{$level_2}}) {
            for my $type (sort keys %{$extend_hash{$level_1}{$level_2}{$level_3}} ) {
                print "$level_1, $level_2, $level_3 $type" . " $extend_hash{$level_1}{$level_2}{$level_3}{$type}" ."\n" ;
                }
         }
    }
}

知道了 - I_alarmed_alien 惊人的工作输出了一个散列的散列的散列的散列的散列的散列的散列的散列的散列的散列的散列的散列

6, XLNX, AMXO , specialist 1
6, XLP, AMXO , penny 0
6, XLP, AMXO , specialist 1
6, XLP, XISX , penny 0
6, XLP, XISX , specialist 1
6, XLV, AMXO , penny 0
6, XLV, AMXO , specialist 1
6, XLY, AMXO , penny 0
6, XLY, AMXO , specialist 1
6, YUM, AMXO , penny 0
6, YUM, AMXO , specialist 1
6, ZINC, XISX , penny 0
6, ZINC, XISX , specialist 1
6, ZMH, AMXO , penny 0
6, ZMH, AMXO , specialist 1

【问题讨论】:

  • 只需在您的打印语句中添加$type -- 即print "$level_1, $level_2, $level_3, $type, " . " $extend_hash{$level_1}{$level_2}{$level_3}{$type}" ."\n"

标签: perl hashmap dereference perl-data-structures multi-level


【解决方案1】:

您的代码就快完成了。以下是到达哈希底部的方法:

foreach my $l1 (keys %extend_hash) {
    # '6'
    foreach my $l2 (keys %{$extend_hash{$l1}}) {
        # IACI, MCHP, BC, etc.
        foreach my $l3 (keys %{$extend_hash{$l1}{$l2}}) {
            # ARCX, AMXO, XISX, etc.
            foreach my $k (keys %{$extend_hash{$l1}{$l2}{$l3}}) {
                print "$l1, $l2, $l3, $k, " . $extend_hash{$l1}{$l2}{$l3}{$k} . "\n";
            }
        }
    }
}

请注意,哈希键不是以任何特定顺序访问的,因此您可能需要对它们进行排序——例如foreach my $l1 (sort keys %extend_hash).

散列的散列的散列很有趣! ;)

ETA:这是一个更通用的函数,用于递归到任意深度的 hashes-of-hashes-of-hashes-of...

sub print_hash {
    # href = reference to the hash we're examining (i.e. \%extend_hash)
    # so_far = arrayref containing the hash keys we are accessing
    my $href = shift;
    my $so_far = shift;
    foreach my $k (keys %$href) {
        # put $k on to the array of keys
        push @$so_far, $k;
        # if $href->{$k} is a reference to another hash, call print_hash on that hash
        if (ref($href->{$k}) eq 'HASH') {
            print_hash($href->{$k}, $so_far);
        } else {
        # $href->{$k} is a scalar, so print out @$so_far (our list of hash keys)
        # and the value in $href->{$k}
            print join(", ", @$so_far, $href->{$k}) . "\n";
        }
        # we've finished looking at $href->{$k}, so remove $k from the array of keys
        pop @$so_far;
    }
}

print_hash($hash, []);

【讨论】:

  • 10 级嵌套散列呢?还是未知号码?
  • 我刚刚回答了这个特定的问题。如果你不知道散列的深度,你可以使用递归函数——当你遍历散列键和值时,检查值是标量还是另一个散列;如果是散列,请在其上调用您的散列打印函数。
  • @M42 添加了用于遍历任意深度哈希的递归函数。
【解决方案2】:

遍历整个结构并创建逗号分隔的表(快速而肮脏,但可行的解决方案):

my $VAR1 = <insert the hash here>

sub printval
{
    my ($val, $path) = @_;
    if (ref($val) eq "HASH")
    {
        printval ($val->{$_}, ($path?"$path,":"")."$_") foreach (keys %{$val});
    }
    else
    {
        print "$path,$val\n";
    }
}

printval($VAR1);

【讨论】:

    【解决方案3】:
    use Data::Dumper;
    
    print Dumper %extend_hash;
    

    【讨论】:

    • 谢谢,数据转储器非常适合验证信息 - 我确实打印出了数据转储器中的信息(见上文)我需要将扩展​​哈希中的所有列打印成逗号分隔文件 - 格式见上文。
    【解决方案4】:

    如果您只想打印,请使用 Data::Dumper http://perldoc.perl.org/Data/Dumper.html

    要检查某个变量是否是哈希引用,请使用:

    if (ref($r) eq "HASH") {
      print "r is a reference to a hash.\n";
    }
    

    【讨论】:

    • 我一直试图在上面的脚本中实现这一点 - 弄清楚哈希中的什么是对什么的引用,我不明白如何工作。
    猜你喜欢
    • 1970-01-01
    • 2011-10-27
    • 1970-01-01
    • 2020-10-16
    • 2012-07-22
    • 1970-01-01
    • 1970-01-01
    • 2014-04-15
    • 2017-09-30
    相关资源
    最近更新 更多