Perl从阵列结构的哈希中解除引用

时间:2013-08-01 01:36:42

标签: perl hash

我有一个数组和哈希的哈希,如下所示:

$VAR1 = \{
           'abc' => {
                       'def' => 'WorkSet',
                       'products' => [
                                       {
                                         'prodtype' => 'Dell',
                                         'product' => 'Powerconnect-5600'
                                       },
                                       {
                                         'prodtype' => 'Dell',
                                         'product' => 'R-720'
                                       },
                                       {
                                         'prodtype' => 'Dell',
                                         'product' => 'R-920'
                                       }
                                     ]
                     },
        '123' => {
                        '456' => 'WorkSet',
                        'products' => [
                                        {
                                          'prodtype' => 'Dell',
                                          'product' => '210'
                                        },
                                        {
                                          'prodtype' => 'Dell',
                                          'product' => 'TZ-200'
                                        },
                                        {
                                          'prodtype' => 'Dell',
                                          'product' => 'TZ-200'
                                        },
                                       ]
          }
 }

我想有这样的:

  Branch: Workset
  Build Number: abc
  product : Dell producttype : PowerConnect-5600
  product : Dell producttypr : R-720
  product : Dell producttype : R-920

哈希值123也应该相同。

我知道单独使用上面的哈希,但发现很难在循环中进行。

请给我你的指导。

仅供参考,我已使用Data:Dumper perl模块列出了上述哈希值。

        This is what I thought and tried but not getting the required answer in loops:

  my @unique = uniq @version;
  foreach $version(@ unique){
  my $i=0;
  print "$list->{$version}{branch}\n";
  print "$list->{$version}->{products}->[$i]->{product}\n";
  $i=$i+1;
  } where @unique = qw (abc,123)

4 个答案:

答案 0 :(得分:1)

这将取消引用您的结构(前提是每个构建号只有2个元素 - 分支和数组或产品)。您将'产品'作为'prodtype'(例如prodtype => Dell),在您的哈希中,'prodtype'作为'产品' - 与名称相反。您应该考虑按照Jason Gray的建议改进数据结构。

#!/usr/bin/perl
use strict;
use warnings;

my $hash = {
           'abc' => {
                       'def' => 'WorkSet',
                       'products' => [
                                       {
                                         'prodtype' => 'Dell',
                                         'product' => 'Powerconnect-5600'
                                       },
                                       {
                                         'prodtype' => 'Dell',
                                         'product' => 'R-720'
                                       },
                                       {
                                         'prodtype' => 'Dell',
                                         'product' => 'R-920'
                                       }
                                     ]
                     },
        '123' => {
                        '456' => 'WorkSet',
                        'products' => [
                                        {
                                          'prodtype' => 'Dell',
                                          'product' => '210'
                                        },
                                        {
                                          'prodtype' => 'Dell',
                                          'product' => 'TZ-200'
                                        },
                                        {
                                          'prodtype' => 'Dell',
                                          'product' => 'TZ-200'
                                        },
                                       ]
          }
};

while (my ($build_num, $href) = each %$hash) {
    my ($branch, $aref);
    for my $key (keys %$href) {
        if (ref($href->{$key}) eq 'ARRAY') {
            $aref = $href->{$key};  
        }
        else {
            $branch = $href->{$key};    
        }
    }
    print "Branch: $branch\n";
    print "Build Number: $build_num\n";

    for my $href (@$aref) {
        print "product: $href->{prodtype} prodtype: $href->{product}\n";
    }
    print "\n";
}

将输出打印为:

Branch: WorkSet
Build Number: 123
product: Dell prodtype: 210
product: Dell prodtype: TZ-200
product: Dell prodtype: TZ-200

Branch: WorkSet
Build Number: abc
product: Dell prodtype: Powerconnect-5600
product: Dell prodtype: R-720
product: Dell prodtype: R-920

答案 1 :(得分:1)

但是,我意识到这不完全是您的数据结构。我提供了一个你可以稍微采用不同方法的方法的例子。

use strict;
use warnings;
use feature 'say';

my $h = {
      abc => {
          Workset => { 
                       Dell => [ 
                                 'Powerconnect-5600', 
                                 'R-270', 
                                 'R-920', 
                               ],
                     },
             },
      123 => {
          Workset => {
                       Dell => [
                                 '210',
                                 'TZ-200',
                               ],
                     },
             },
};

for my $k ( keys %$h ) {
   for my $j ( keys %$h->{$k} ) {
      for my $prod ( keys %$h->{$k}{$j} ) {
         say "Branch: $j";
         say "Build Number: $k";
         say "product : $prod producttype : " . $_ for @{ $h->{$k}{$j}{$prod} };
      }
   }
}

输出:

Branch: Workset
Build Number: 123
product : Dell producttype : 210
product : Dell producttype : TZ-200

Branch: Workset
Build Number: abc
product : Dell producttype : Powerconnect-5600
product : Dell producttype : R-270
product : Dell producttype : R-920

答案 2 :(得分:1)

问题已经得到解答和接受,但无论如何我必须打开我的陷阱......

首先,我认为你的结构是关闭的。它应该是这样的:

$VAR1 = {
          '123' => bless( {
                            'ARRAY' => [
                                         bless( {
                                                  'PRODUCT' => 'Dell',
                                                  'TYPE' => '210'
                                                }, 'Product' ),
                                         bless( {
                                                  'PRODUCT' => 'Dell',
                                                  'TYPE' => 'TZ-200'
                                                }, 'Product' ),
                                         bless( {
                                                  'PRODUCT' => 'Dell',
                                                  'TYPE' => 'TZ-200'
                                                }, 'Product' )
                                       ]
                          }, 'Build' ),
          'abc' => bless( {
                            'ARRAY' => [
                                         bless( {
                                                  'PRODUCT' => 'Dell',
                                                  'TYPE' => 'Powerconnect-5600'
                                                }, 'Product' ),
                                         bless( {
                                                  'PRODUCT' => 'Dell',
                                                  'TYPE' => 'R-720'
                                                }, 'Product' ),
                                         bless( {
                                                  'PRODUCT' => 'Dell',
                                                  'TYPE' => 'R-920'
                                                }, 'Product' )
                                       ]
                          }, 'Build' )
        };

我基于你想要的输出。看起来你有 Builds ,它包含一系列产品。产品包含产品类型产品描述。在您的原始结构中,您有:

 `456` => Workset`

但结构的这一部分毫无意义,你不使用它。也许你的意思是分支类型?很难说。让其他一切我都不理解,我忽略了它。

现在,你应该如何解析这个结构?您应该使用Perl Object Oriented Programming。这使您可以不再担心数据结构。你的课程定义将负责这一点。如果这是散列数组,散列或数组,或者数组或数组的哈希值,您不必担心。

这是整个主程序。两个循环:在第一个循环中,我读入数据(由三个制表符分隔的项目组成:构建号,产品类型和产品)。它清晰,简洁,易于理解。只需要六行代码就可以解析整个数据结构:

use strict;
use warnings;
use feature qw(say);

my %workset;
my $prev_build;

#
# Read in the Data
#
while ( my $line = <DATA> ) {
    chomp $line;
    my ($build_num, $prodtype, $description) = split /\t/, $line;
    my $product = Product->new( $prodtype, $description );
    if ( not $prev_build or $prev_build ne $build_num ) {
        $workset{$build_num} = Build->new;
        $prev_build = $build_num;
    }
    $workset{$build_num}->Push($product);
}

#
# Parse the structure and Print it out
#
for my $workset ( sort keys %workset ) {
    say "Build Number: " . $workset;
    while (  my $product = $workset{$workset}->Pop ) {
        say "Product: " . $product->Product . " Prodtype: " . $product->Type;
    }
}

这是输出:

Build Number: 123
Product: Dell Prodtype: TZ-200
Product: Dell Prodtype: TZ-200
Product: Dell Prodtype: 210
Build Number: abc
Product: Dell Prodtype: R-920
Product: Dell Prodtype: R-720
Product: Dell Prodtype: Powerconnect-5600

就像你想要的那样。

我的程序的其余部分是类定义。大多数时候,我只是将定义附加到主程序的末尾,因为我再也没有使用它们。尽管如此,使用面向对象的代码使编程变得更快更容易。

这是我程序的其余部分:

package Product;

sub new {
    my $class   = shift;
    my $product = shift;
    my $type        = shift;

    my $self = {};
    bless $self, $class;

    $self->Product($product);
    $self->Type($type);

    return $self;
}

sub Product {
    my $self        = shift;
    my $product = shift;

    if ( defined $product ) {
        $self->{PRODUCT} = $product;
    }
    return $self->{PRODUCT};
}

sub Type {
    my $self = shift;
    my $type = shift;

    if ( defined $type ) {
        $self->{TYPE} = $type;
    }
    return $self->{TYPE};
}

package Build;
use Carp;

sub new {
    my $class = shift;

    my $self = {};
    bless $self, $class;

    return $self;
}

# PRIVATE -- No peeking
sub _Array_ref {
    my $self = shift;

    if ( not exists $self->{ARRAY} ) {
        $self->{ARRAY} = [];
    }
    return $self->{ARRAY};
}

sub Index {
    my $self  = shift;
    my $index = shift;

    if ( not defined $self->{INDEX} ) {
        $self->{INDEX} = 0;
    }

    if ( defined $index ) {
        $self->{INDEX} = $index;
    }

    if ( $self->{INDEX} < 0 or $self->{INDEX} > $self->Size ) {
        croak qq(Index out of range: Set to "$index");
    }

    return $self->{INDEX};
}

sub Array {
    my $self = shift;
    my @array = @{ $self->_Array_ref };

    return wantarray ? @array : \@array;
}

sub Size {
    my $self = shift;

    my $array_ref = $self->_Array_ref;
    return $#{ $array_ref };
}

sub Push {
    my $self    = shift;
    my $product = shift;

    if ( not defined $product or not $product->isa("Product") )  {
        croak qq(Push Method for requires a Product Class to push);
    }

    my $array_ref = $self->_Array_ref;
    push @{ $array_ref }, $product;

    return $#{ $array_ref };
}

sub Pop {
    my $self = shift;

    my $array_ref = $self->_Array_ref;
    return pop @{ $array_ref };
}

sub Next {
    my $self = shift;

    my $index = $self->Index;
    my $array_ref = $self->_Array_ref;
    $index += 1;
    $self->Index($index);

    return ${ $array_ref }[$index];
}

sub Prev {
    my $self = shift;

    my $index = $self->Index;
    my $array_ref = $self->_Array_ref;
    $index -= 1;
    $self->Index($index);

    return ${ $array_ref }[$index];
}

package main;

__DATA__
abc Dell    Powerconnect-5600
abc Dell    R-720
abc Dell    R-920
123 Dell    210
123 Dell    TZ-200
123 Dell    TZ-200

答案 3 :(得分:0)

这也有效:

    while (my ($build_num, $href) = each %$list) {
    my ($branch, $aref, $username);
    $aref = $href->{'products'};
    $branch = $href->{branch};
    $username = $href->{user};

    for my $href (@$aref) {
     print "product: $href->{prodtype}     prodtype: $href->{product}       qbs_id:$href->{qbs_id}\n";
   }

刚刚编辑了@Chris答案并进行了一些简单的修改而不使用ref ..谢谢你