2013-07-27 4 views
2

Я хочу создать 10 одномерных массивов и поместить эти 10 одномерных массивов в один одномерный массив и хранить некоторые данные в определенном индексе массива.Как перенести данные в многомерный массив?

но вывод, что я ожидаю должен быть

expect output   real output 
    0      1 
    1      1 
    0      1 
    3      1 
    0      1 
    5      1 
    0      1 
    7      1 
    0      1 
    0      1 

вот мой код

@Hits =(); 

# Create 10 one dimension array 
for($i=0;$i<=9;$i++) 
{ 
    @Space =(); 
    push(@Hits,\@Space); 
} 

# Store some data to some index 
push(@{$Hits[1]},1); 
push(@{$Hits[3]},3); 
push(@{$Hits[5]},5); 
push(@{$Hits[7]},7); 

# print the first element of 10 arrays 
for($i=0;$i<=9;$i++) 
{ 
    print $Hits[$i]->[0]; 
    print "\n"; 
} 

благодаря

ответ

5

Проблема в том, что вы не правильно объявляете свои переменные. Для каждого сценария, вы должен

use strict; use warnings; 

Это запрещает общие источники ошибок, предупреждает о ненадежном материале, и заставляет вас правильно объявлять все переменные.

По умолчанию все необъявленные переменные считаются глобальными. Таким образом, в

for($i=0;$i<=9;$i++) 
{ 
    @Space =(); 
    push(@Hits,\@Space); 
} 

@Space относится к тому же массиву в каждой итерации. Ergo, все десять записей в @Hits являются ссылкой на тот же массив. Давайте проверим, что такое @Hits. Мы можем сделать это с Data::Dumper или на Data::Dump модуль (последняя обычно производит покрасивее выход):

use Data::Dump; # use Data::Dumper; 
dd \@Hits;  # print Dumper \@Hits; 

Мы получаем с Data::Dumper (легче понять):

$VAR1 = [ 
      [ 
      1, 
      3, 
      5, 
      7 
      ], 
      $VAR1->[0], 
      $VAR1->[0], 
      $VAR1->[0], 
      $VAR1->[0], 
      $VAR1->[0], 
      $VAR1->[0], 
      $VAR1->[0], 
      $VAR1->[0], 
      $VAR1->[0] 
     ]; 

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

my $foo = 123; 

Когда мы имеем цикл, как

my @Hits; 
for my $i (0 .. 9) { 
    my @Space; 
    push @Hits, \@Space; 
} 

, то каждый раз, когда my выполняется, мы получаем новый@Space. О, и я использовал петлю foreach, которая повторяется в диапазоне 0 .. 9 с (лексической) переменной $i. Мне это легче понять, чем циклы стиля C, которые вы использовали.

Поскольку каждый элемент в @Hits теперь является различными arrayref, мы получаем ожидаемую структуру данных.Как Data::Dump выхода:

[[], [1], [], [3], [], [5], [], [7], [], []] 

Когда мы теперь выполнить свой цикл, который печатает первое значение каждого суб-массив, то вы можете быть удивлены пустыми линиями между numebers. Это происходит потому, что, например, первый arrayref не имеет записи в индексе 0 и поэтому возвращает специальное значение undef. При использовании в качестве строки это пустая строка. Если вы следовали моему совету и сделали use warnings, вы также получите сообщение о том, что вы печатаете неинициализированное значение.

Мы можем решить это путем тестирования на определенность и предоставления нулевого значения в противном случае. Начиная с perl5 v10, мы можем использовать определенный или оператор // для этого (на ранних perls, || логический или должен делать).

for my $i (0 .. 9) { 
    my $value = $Hits[$i][0] // 0; 
    print "$value\n"; 
} 

Есть несколько других битов мы можем улучшить:

  • Мы не должны создавать вручную @Space массивы; Perl делает это за кулисами, когда вы разыгрываете запись в виде массива, например @{ $Hits[$i] }. Это называется автовивизация.
  • Мы можем не только перебирать диапазоны, но и массивы. Это намного лучше, чем индексы жесткого кодирования.
  • Начиная с версии 10, вы можете использовать функцию say. Функция say точно такая же, как print, но добавляет новую строку в конце.

Вот как я написал этот код:

#!/usr/bin/perl 
use strict; use warnings; use feature 'say'; 

my @Hits; 

for my $i (1, 3, 5, 7) { 
    push @{ $Hits[$i] }, $i; 
} 

for my $arrayref (@Hits) { 
    say $arrayref->[0] // 0; 
} 

Выход:

0 
1 
0 
3 
0 
5 
0 
7 

(Обратите внимание, что мы никогда не инициализируются значения в позициях 8 и 9, таким образом, они не являются Мы можем исправить это, выполнив итерацию по фрагменту @Hits[0 .. 9].)

1

Я изменить свой код, как следующее:

#! /usr/bin/perl -w 
@Hits =(); 

push(@{$Hits[1]},1); 
push(@{$Hits[3]},3); 
push(@{$Hits[5]},5); 
push(@{$Hits[7]},7); 

#print the content of 
for($i=0;$i<=9;$i++) 
{ 
    if (defined ($Hits[$i])) { 
     print "$Hits[$i][0]\n"; 
    } else { 
     print "0\n"; 
    } 
} 

Это неправильно дайте ref @space @Hits и это сделает неправильный результат. Нет необходимости в исходных @Hits в perl.

0
perl -e "use Data::Dump; @sf=(); push @{$sf[0]},"0"; push @{$sf[1]},"1"; dd \@sf;" 
[[0], [1]] 

или

perl -e "use Data::Dump; @sf=(); push @sf,["0"]; push @sf,["1"]; dd \@sf;" 
[[0], [1]] 
Смежные вопросы