Perl Хеши и массив - PullRequest
       3

Perl Хеши и массив

2 голосов
/ 07 августа 2010

У меня есть массив с 28 элементами.

Я скопировал содержимое массива в хеш.

Если я пытаюсь напечатать хэш, он не показывает все ключи и значения.

Код указан ниже,

@new;
%hash = @new;
foreach $food (keys %hash) 
{
 $color = $hash{$food};
 print "$food is $color.\n";
}

Вывод ::

attribute is Mandatory.
min is 0X00.
value is 778.
max is 9940486857.
name is Security_header.
type is nibble.

Массив @new содержимого:

name Protocol_discriminator attribute Mandatory value 778 min 0X00 max 994048685 value 7 min 0 max F name Security_header attribute Mandatory type nibble value 778 min 0X00 max 9940486857

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

Может ли кто-нибудь помочь преодолеть эту проблему. Я борюсь за последние два дня.

Спасибо Senthil.

Ответы [ 4 ]

6 голосов
/ 07 августа 2010

Давайте изменим представление @new, чтобы показать, что происходит:

my @new = qw/
  attribute Mandatory
  attribute Mandatory
  max       994048685
  max       9940486857
  max       F
  min       0
  min       0X00
  min       0X00
  name      Protocol_discriminator
  name      Security_header
  type      nibble
  value     7
  value     778
  value     778
/;

Ключи хэша Perl уникальны, поэтому при присвоении @new значению %hash последнее значение для данной клавиши «выигрывает». Для простого примера

$ perl -le '%h = qw/1 a 1 b 1 c/; print $h{1}'
c

Учитывая, что у вас много значений для одного и того же ключа, используйте структуру данных, которая может его обработать:

my %hash;
for (my $i = 0; $i < @new; $i += 2) {
  my($name,$val) = @new[$i,$i+1];
  push @{ $hash{$name} } => $val;
}

Если вы не против уничтожить @new, код может быть немного более идиоматическим:

while (@new) {
  my($name,$val) = splice @new, 0, 2;
  push @{ $hash{$name} } => $val;
}

Это означает, что каждое значение, связанное с данным ключом в %hash, является ссылкой на массив значений. Оператор push ожидает массив, а не ссылку, поэтому мы используем @{ ... } для разыменования его.

Если вы не знакомы с ссылками на Perl, обязательно прочитайте документацию perlref и perllol .

Один из способов печати значений в %hash - это

foreach my $name (sort keys %hash) {
  print "$name = [@{ $hash{$name} }]\n";
}

Выход:

attribute = [Mandatory Mandatory]
max = [994048685 9940486857 F]
min = [0 0X00 0X00]
name = [Protocol_discriminator Security_header]
type = [nibble]
value = [7 778 778]

Еще одним удобным трюком для печати и отладки сложных структур данных является модуль Data::Dumper:

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

который печатает

$VAR1 = {
          'attribute' => [
                           'Mandatory',
                           'Mandatory'
                         ],
          'value' => [
                       '7',
                       '778',
                       '778'
                     ],
          'min' => [
                     '0',
                     '0X00',
                     '0X00'
                   ],
          'name' => [
                      'Protocol_discriminator',
                      'Security_header'
                    ],
          'max' => [
                     '994048685',
                     '9940486857',
                     'F'
                   ],
          'type' => [
                      'nibble'
                    ]
        };
6 голосов
/ 07 августа 2010

У вас есть несколько ключей с одним и тем же именем, поэтому вы перезаписываете данные.

Вам необходимо переосмыслить свой подход.

Возможно, вам нужен более умный алгоритм для построения хэша (например,помещая значения в массив ref вместо простого значения).Возможно, вам нужно забыть о хэше и просто зациклить массив с циклом for, который увеличивается на 2 каждый раз.

2 голосов
/ 07 августа 2010

Информация в массиве @new предполагает, что вам нужна более богатая структура данных. Я не знаю деталей вашей проблемы, но вот структуру, которую я вижу.

my @data = (
    # Each data item is a hash reference, with four
    # possible keys: name, attribute, type, and vals.
    # I added the 'vals' key to handle the other information.
    {
        name      => 'Protocol_discriminator',
        attribute => 'Mandatory',
        type      => undef,
        # The 'vals' key points to an array reference.
        # That array contains a list of hash references.
        vals => [
            { value => 778, min => '0X00', max => 994048685 },
            { value =>   7, min =>      0, max =>       'F' },
        ],
    },

    # Another data item.
    {
        name      => 'Security_header',
        attribute => 'Mandatory',
        type      => 'nibble',
        vals => [
            { value => 778, min => '0X00', max => 9940486857 },
        ],
    },
);

Чтобы узнать, как работать со сложными структурами данных, см. perlreftut , perldsc и perllol .

Кроме того, ваши сценарии всегда должны содержать use strict и use warnings.

1 голос
/ 08 августа 2010

Простой ответ: Хеш следует рассматривать как ассоциативный массив.
Существует один уникальный ключ, и каждый ключ имеет значение (может быть хешем).

Ваша проблема: Каждый раз, когда вы сталкиваетесь с ключом, который уже существует, вы заменяете значение.


Решение:

#!/usr/bin/perl -w    

use strict;   

   sub main{ 
      $" = ", ";                                         # format array output

      my %hash;   
      my @arr   =  ( ['color' ,'red' ]
                   , ['color' ,'blue']
                   , ['size'  ,'1'   ]
                   , ['size'  ,'2'   ] 
                   );

      foreach my $rcd (@arr) {
         push @{$hash{$$rcd[0]}} , $$rcd[1];
      }          

      print "@{$hash{color}} \n";                        # prints: red, blue
   }    

   main();  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...