Как создать хеш с дублирующимися ключами - PullRequest
0 голосов
/ 23 декабря 2011

Теперь я немного изменяю код. Я использую код для создания хеш-кода с дублирующимися ключами.Это дает синтаксическую ошибку.

use strict;
use warnings;
my $s = "12   A    P1  
23   B    P5
24   C    P2
15   D    P1
06   E    P5";
my $hash;
my @a  = split(/\n/, $s);
foreach (@a)
{
  my $c = (split)[2];
  my $d = (split)[1];
  my $e = (split)[0];
  push(@{$hash->{$c}}, $d);
}
print Dumper($hash );

Я получаю вывод как

    $VAR1 = {
          'P5' => [
                    'B',
                    'E'
                  ],
          'P2' => [
                    'C'
                  ],
          'P1' => [
                    'A',
                    'D'
                  ]
        };

Но я хочу вывод как

    $VAR1 = {
      'P5' => {
      'E' => '06',
      'B' => '23'
     },
     'P2' => {
      'C' => '24'
    },
    'P1' => {
      'A' => '12',
      'D' => '15'
      }
     };

Как это сделать

Ответы [ 5 ]

4 голосов
/ 23 декабря 2011

Ваше хеш-объявление неверно, оно должно быть:

my %hash = ();

или просто:

my %hash;

Тогда остальная часть вашего кода будет слишком сложной и неправильной.

foreach (@a) {
  my ($k, $v) = (split);
  push @{$hash{$k}}, $v;
}

должно быть достаточно. См. Автовивификация , почему это работает.

С вашим кодом, когда вы впервые видите ключ, вы устанавливаете $hash{$k} как скаляр. Тогда вы не можете push что-то с этим ключом - для начала он должен быть массивом.

Тест if (-e $hash{$c}) неверен. -e - это проверка файла существования. Если вы хотите узнать, существует ли ключ хеша, используйте:

if (exists $hash{$c}) { ... }

И print %hash; не будет делать то, что вы ожидаете (и print %{$hash}; недействительно). Вы получите более симпатичный дисплей, если сделаете:

use Data::Dumper;
print Dumper(\%hash);

(Отличная отладка, это Data::Dumper.)

2 голосов
/ 23 декабря 2011

Perl говорит вам точно, что не так. Вы использовали прагму strict, поэтому использование переменной %hash без объявления ее является синтаксической ошибкой. В то время как строка %hash не появляется в вашем коде, строка $hash{...} появляется в каждой из проблемных строк. Это синтаксис для доступа к элементу %hash, поэтому строгие жалуются.

Вы объявили переменную $hash, поэтому для доступа к элементу содержащейся ссылки на хеш написано $$hash{...} или $hash->{...}. Исправьте проблемные строки для доступа к правильной переменной, и код скомпилируется.

2 голосов
/ 23 декабря 2011

%hash - это хеш, а $hash - скаляр (хеш-ссылка, например, \%hash), это две разные переменные

Для обозначения $hash, для обозначенияхэш, ссылка на который хранится в скалярной переменной $hash, вы должны использовать $hash->{$c} или $$hash{$c}

См. Краткий справочник ссылок

обновление:

#!/usr/bin/perl --
use strict; use warnings;
use Data::Dumper;

my $s = "P1 26 
P5 23
P2 24
P1 15
P5 06 ";

my $hash = {};

for my $line ( split  /[\r\n]+/, $s ) {
    my( $c, $d ) = split ' ', $line;
    push @{ $hash->{$c} }, $d;
}
print Dumper( $hash );
__END__
$VAR1 = {
          'P5' => [
                    '23',
                    '06'
                  ],
          'P2' => [
                    '24'
                  ],
          'P1' => [
                    '26',
                    '15'
                  ]
        };
1 голос
/ 23 декабря 2011

См. Рабочий код, исправленные ошибки (комментарии в коде) и полученный результат:

use strict;
use warnings;
my $s = "P1 26 
P5 23
P2 24
P1 15
P5 06 ";
my %hash; #my $hash ={};
#my $arr = [];
my @a  = split(/\n/, $s);

foreach (@a)
{
    my $d = (split)[1];
    my $c = (split)[0];
    push(@{$hash{$c}}, $d); #if ...
}
while (my ($key, $value) = each(%hash)) #print %{$hash};
{
     print "$key @{$value}\n";
}

#Output:
#P5 23 06
#P2 24
#P1 26 15
0 голосов
/ 22 января 2012

(Странно. Из всех опубликованных ответов пока никто не ответил на вопрос ...)

Приведенный ниже код дает запрашиваемый результат. Основной бит, который, по-видимому, отсутствует в исходном коде, - это двухуровневый хеш.

Как и в стороне, кажется, нет никакой причины для того, чтобы внешний хэш был хеш-рефом, а не хеш-кодом, поэтому я сделал это хеш-кодом. Также вы можете выделить разделение на переменные в одной строке.

use strict;
use warnings;
use Data::Dumper;
my $s = "12   A    P1
23   B    P5
24   C    P2
15   D    P1
06   E    P5";
my %hash;
my @a  = split(/\n/, $s);
foreach (@a)
{
  my ($e, $d, $c) = (split);
  $hash{$c}{$d} = $e;
}
print Dumper(\%hash);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...