2015-11-27 4 views
-1

Я стою с пониманием функциональности HASH. С циклом «for» я динамически создаю хеши и «hashnames», и я кормлю их некоторыми элементами key/values. К сожалению, эти значения больше не видны вне цикла. Ниже небольшого кода, который я использую, и их вывода.Perl: hash, поданный в цикл for, пуст вне цикла

#!/usr/bin/perl -w 

use warnings; 
use English; 
use Data::Dumper; 

@wA = ("a", "b", "c", "d", "e", "f"); 
@dA = (1, 2, 3, 4, 5, 6); 

for (my $i=0; $i<=$#wA; $i++){ 
    $hn = "hash-$wA[$i]"; 
    push(@hna, $hn); 
    %hn =(); 
    #my %hn; 
    $hsize = @hn; 
    print "1. HashName: " . $hn . " Size: " . $hsize . "\n"; 
    print "HashName: $hn\n"; 
    if ($i == 0){ 
     print "Feed the hash $hn: "; 
     for (my $j=$i; $j<=$#dA; $j++){ 
      $hn{ $dA[$j] } = $wA[$j]; 
      print "$dA[$j] => $wA[$j], "; 
     } 
     print "\n"; 
    } 
    if ($i == 1){ 
     print "Feed the hash $hn: "; 
     for (my $j=$i; $j<=$#dA; $j++){ 
      $hn{ $dA[$j] } = $wA[$j]; 
      print "$dA[$j] => $wA[$j], "; 
     } 
     print "\n"; 
    } 
    if ($i == 2){ 
     print "Feed the hash $hn: "; 
     for (my $j=$i; $j<=$#dA; $j++){ 
      $hn{ $dA[$j] } = $wA[$j]; 
      print "$dA[$j] => $wA[$j], "; 
     } 
     print "\n"; 
    } 
    if ($i == 3){ 
     print "Feed the hash $hn: "; 
     for (my $j=$i; $j<=$#dA; $j++){ 
      $hn{ $dA[$j] } = $wA[$j]; 
      print "$dA[$j] => $wA[$j], "; 
     } 
     print "\n"; 
    } 
    if ($i == 4){ 
     print "Feed the hash $hn: "; 
     for (my $j=$i; $j<=$#dA; $j++){ 
      $hn{ $dA[$j] } = $wA[$j]; 
      print "$dA[$j] => $wA[$j], "; 
     } 
     print "\n"; 
    } 
    if ($i == 5){ 
     print "Feed the hash $hn: "; 
     for (my $j=$i; $j<=$#dA; $j++){ 
      $hn{ $dA[$j] } = $wA[$j]; 
      print "$dA[$j] => $wA[$j], "; 
     } 
     print "\n"; 
    } 
    if ($i == 6){ 
     print "Feed the hash $hn: "; 
     for (my $j=$i; $j<=$#dA; $j++){ 
      $hn{ $dA[$j] } = $wA[$j]; 
      print "$dA[$j] => $wA[$j], "; 
     } 
     print "\n"; 
    } 
    @hk = keys %hn; 
    $hsize = @hk; 
    print "2. HashName: " . $hn . " Size: " . $hsize . "\n"; 
} 

print "\n"; 
print "Araay with hashNames: " . @hna . " Array length: " . $#hna . "\n"; 
print "\n\n\n"; 

print "Hash info out of the FOR loop\n"; 

for (my $k=0; $k<=$#hna; $k++){ 
    @hnaca = keys %{$hna[$k]}; 
    #@hnaca = keys @{ @hna[$k] }; 
    #@hnaca = keys \%{ $hna[$k] }; 
    #@hnaca = keys %{ $hna->[$k] }; 
    print "Element: " . $k . " HashName: " . $hna[$k] . " Size(\$#): " . $#hnaca . " Size(\@): " . @hnaca . "\n"; 
} 

И выход, как показано ниже:

1. HashName: hash-a Size: 0 
HashName: hash-a 
Feed the hash hash-a: 1 => a, 2 => b, 3 => c, 4 => d, 5 => e, 6 => f, 
2. HashName: hash-a Size: 6 
Data::Dumper: 1. HashName: hash-b Size: 0 
HashName: hash-b 
Feed the hash hash-b: 2 => b, 3 => c, 4 => d, 5 => e, 6 => f, 
2. HashName: hash-b Size: 5 
Data::Dumper: 1. HashName: hash-c Size: 0 
HashName: hash-c 
Feed the hash hash-c: 3 => c, 4 => d, 5 => e, 6 => f, 
2. HashName: hash-c Size: 4 
Data::Dumper: 1. HashName: hash-d Size: 0 
HashName: hash-d 
Feed the hash hash-d: 4 => d, 5 => e, 6 => f, 
2. HashName: hash-d Size: 3 
Data::Dumper: 1. HashName: hash-e Size: 0 
HashName: hash-e 
Feed the hash hash-e: 5 => e, 6 => f, 
2. HashName: hash-e Size: 2 
Data::Dumper: 1. HashName: hash-f Size: 0 
HashName: hash-f 
Feed the hash hash-f: 6 => f, 
2. HashName: hash-f Size: 1 
Data::Dumper: 
Araay with hashNames: 6 Array length: 5 



Hash info out of the FOR loop 
Element: 0 HashName: hash-a Size($#): -1 Size(@): 0 -> expected 5/6 
Element: 1 HashName: hash-b Size($#): -1 Size(@): 0 -> expected 4/5 
Element: 2 HashName: hash-c Size($#): -1 Size(@): 0 -> expected 3/4 
Element: 3 HashName: hash-d Size($#): -1 Size(@): 0 -> expected 2/3 
Element: 4 HashName: hash-e Size($#): -1 Size(@): 0 -> expected 1/2 
Element: 5 HashName: hash-f Size($#): -1 Size(@): 0 -> expected 0/1 

Как я могу получить ожидаемые значения?

+0

Существует много неправильно с вашей программой в дополнение к ответу вы приняли, но это очень трудно понять, что вы пытаетесь сделать, и действительно, что * «ожидаемые значения» * могут быть. Вам нужно начать с добавления 'use strict', а также' use warnings 'all''; наверняка вы видели совет, чтобы сделать это на * каждой * Perl-программе, которую вы пишете? Но если вы лучше объясните, на что нацелитесь, то получите гораздо лучшую помощь. – Borodin

+0

Вы, кажется, делаете что-то ужасное [эта статья] (http://perl.plover.com/varvarname.html) объясняет, почему использование переменной as переменное имя неприятно. Следует также отметить: '$ hn' и'% hn' никак не связаны. – Sobrique

ответ

1

Проблема с вашей программой в том, что вы вообще не сохраняете свои хеши. push(@hna, $hn); выталкивает имя хеша в виде строки в @hna. Это единственная переменная, которую вы сохраняете за пределами своего for.

Если вы сохраните имя и хэш, созданный в @hna, выполните следующие действия: push(@hna, {name => $hn, hash => \%hn}); у вас будет больше успеха.

@@ -9,9 +9,7 @@ use Data::Dumper; 

    for (my $i=0; $i<=$#wA; $i++){ 
     $hn = "hash-$wA[$i]"; 
- push(@hna, $hn); 
- %hn =(); 
- #my %hn; 
+ my %hn =(); 
     $hsize = @hn; 
     print "1. HashName: " . $hn . " Size: " . $hsize . "\n"; 
     print "HashName: $hn\n"; 
@@ -73,6 +71,7 @@ for (my $i=0; $i<=$#wA; $i++){ 
     } 
     @hk = keys %hn; 
     $hsize = @hk; 
+ push(@hna, {name => $hn, hash => \%hn}); 
     print "2. HashName: " . $hn . " Size: " . $hsize . "\n"; 
    } 

@@ -83,9 +82,9 @@ print "\n\n\n"; 
    print "Hash info out of the FOR loop\n"; 

    for (my $k=0; $k<=$#hna; $k++){ 
- @hnaca = keys %{$hna[$k]}; 
+ @hnaca = keys %{$hna[$k]->{"hash"}}; 
     #@hnaca = keys @{ @hna[$k] }; 
     #@hnaca = keys \%{ $hna[$k] }; 
     #@hnaca = keys %{ $hna->[$k] }; 
- print "Element: " . $k . " HashName: " . $hna[$k] . " Size(\$#): " . $#hnaca . " Size(\@): " . @hnaca . "\n"; 
+ print "Element: " . $k . " HashName: " . $hna[$k]->{"name"} . " Size(\$#): " . $#hnaca . " Size(\@): " . @hnaca . "\n"; 
    } 

Это дает эту полную программу, которая работает для меня:

#!/usr/bin/perl -w 

use warnings; 
use English; 
use Data::Dumper; 

@wA = ("a", "b", "c", "d", "e", "f"); 
@dA = (1, 2, 3, 4, 5, 6); 

for (my $i=0; $i<=$#wA; $i++){ 
    $hn = "hash-$wA[$i]"; 
    my %hn =(); 
    $hsize = @hn; 
    print "1. HashName: " . $hn . " Size: " . $hsize . "\n"; 
    print "HashName: $hn\n"; 
    if ($i == 0){ 
     print "Feed the hash $hn: "; 
     for (my $j=$i; $j<=$#dA; $j++){ 
      $hn{ $dA[$j] } = $wA[$j]; 
      print "$dA[$j] => $wA[$j], "; 
     } 
     print "\n"; 
    } 
    if ($i == 1){ 
     print "Feed the hash $hn: "; 
     for (my $j=$i; $j<=$#dA; $j++){ 
      $hn{ $dA[$j] } = $wA[$j]; 
      print "$dA[$j] => $wA[$j], "; 
     } 
     print "\n"; 
    } 
    if ($i == 2){ 
     print "Feed the hash $hn: "; 
     for (my $j=$i; $j<=$#dA; $j++){ 
      $hn{ $dA[$j] } = $wA[$j]; 
      print "$dA[$j] => $wA[$j], "; 
     } 
     print "\n"; 
    } 
    if ($i == 3){ 
     print "Feed the hash $hn: "; 
     for (my $j=$i; $j<=$#dA; $j++){ 
      $hn{ $dA[$j] } = $wA[$j]; 
      print "$dA[$j] => $wA[$j], "; 
     } 
     print "\n"; 
    } 
    if ($i == 4){ 
     print "Feed the hash $hn: "; 
     for (my $j=$i; $j<=$#dA; $j++){ 
      $hn{ $dA[$j] } = $wA[$j]; 
      print "$dA[$j] => $wA[$j], "; 
     } 
     print "\n"; 
    } 
    if ($i == 5){ 
     print "Feed the hash $hn: "; 
     for (my $j=$i; $j<=$#dA; $j++){ 
      $hn{ $dA[$j] } = $wA[$j]; 
      print "$dA[$j] => $wA[$j], "; 
     } 
     print "\n"; 
    } 
    if ($i == 6){ 
     print "Feed the hash $hn: "; 
     for (my $j=$i; $j<=$#dA; $j++){ 
      $hn{ $dA[$j] } = $wA[$j]; 
      print "$dA[$j] => $wA[$j], "; 
     } 
     print "\n"; 
    } 
    @hk = keys %hn; 
    $hsize = @hk; 
    push(@hna, {name => $hn, hash => \%hn}); 
    print "2. HashName: " . $hn . " Size: " . $hsize . "\n"; 
} 

print "\n"; 
print "Araay with hashNames: " . @hna . " Array length: " . $#hna . "\n"; 
print "\n\n\n"; 

print "Hash info out of the FOR loop\n"; 

for (my $k=0; $k<=$#hna; $k++){ 
    @hnaca = keys %{$hna[$k]->{"hash"}}; 
    #@hnaca = keys @{ @hna[$k] }; 
    #@hnaca = keys \%{ $hna[$k] }; 
    #@hnaca = keys %{ $hna->[$k] }; 
    print "Element: " . $k . " HashName: " . $hna[$k]->{"name"} . " Size(\$#): " . $#hnaca . " Size(\@): " . @hnaca . "\n"; 
} 
+0

Bolav, спасибо за ваше быстрое решение и объяснение. – user5613599

+3

always 'use strict;' – stevieb

+0

@stevieb Я не собираюсь принуждать кого-либо использовать строгий. – bolav

2

Любопытно, что это то, что вы после ?:

use warnings; 
use strict; 

my @wA = qw(a b c d e f); 
my @dA = qw(1 2 3 4 5 6); 

my %hash; 

for my $w (@wA){ 
    $hash{$w} = shift @dA; 
} 

... или с использованием итератора (реже нам нужны итераторы в Perl). Обратите внимание на использование .. aka. флип-флоп оператора или официально range оператор:

for my $i (0..$#wA){ 
    $hash{$wA[$i]} = $dA[$i]; 
} 

... или даже чуть-чуть более сжато (без явно определенного итератора):

for (0..$#wA){ 
    $hash{$wA[$_]} = $dA[$_]; 
} 

... в конце концов, ты может даже в конечном итоге с этим (так долго, как вы предварительно проверил длину каждого массива):

for (@wA){ 
    $hash{$_} = shift @dA; # requires array length checks 
} 

... еще один (предложенный @Borodin, что я пренебрегали), а slice:

@hash{@wa} = @dA 

Тогда, во всех вышеперечисленных случаях, используйте Dumper, или:

for my $key (keys %hash){ 
    print "$key: $hash{$key}\n"; 
} 
+1

Или даже '@hash {@wa} = @ dA' – Borodin

+0

ohhhh nice. Забыл об этом;) – stevieb

+1

Ваша ссылка была 'splice', которая отличается от' slice'. Исправлена. – Borodin