Создание различных массивов через циклы - PullRequest
1 голос
/ 21 марта 2019

Возможно ли создавать разные именованные массивы во время цикла в Perl?Что мне нужно сделать, это открыть некоторые файлы из @ARGV и поместить их данные в отдельные массивы в одном цикле, например: 1.txt в @first_array, 2.txt в @second_array и т. Д. Возможно ли это и еслида, какой подход был бы наилучшим?

РЕДАКТИРОВАТЬ:

Я думаю, что я все ближе, поскольку Data::Dumper показывает правильную структуру того, что мне нужно,но он не показывает значения файлов, вместо этого он показывает это:

$VAR1 = {
      'skai.txt' => [
                      \*{'::$fh'},
                      $VAR1->{'skai.txt'}[0],
                      $VAR1->{'skai.txt'}[0],
                      $VAR1->{'skai.txt'}[0]
                    ],
      'numb.txt' => [
                      \*{'::$fh'},
                      $VAR1->{'numb.txt'}[0],
                      $VAR1->{'numb.txt'}[0],
                      $VAR1->{'numb.txt'}[0]
                    ]
    };

Каждый файл состоит из 4 чисел.Мой код выглядит так:

use strict;
use warnings;
use Data::Dumper;

my $data = {};

foreach my $arg(@ARGV){
    if(open(my $fh, $arg)){
        $data->{$arg}=[];
        while(<$fh>){
            chomp;
            push @{$data->{$arg}}, $fh;
        }
    close($fh);
    }
}

print Dumper $data;

Что означает \*{'::$fh'}?

Ответы [ 3 ]

2 голосов
/ 21 марта 2019

Это странная часть вашего кода:

push @{$data->{$arg}}, $fh;

$fh - дескриптор файла.Вот почему вы получаете этот вывод.Каждый раз, когда вы зацикливаетесь, вы добавляете в свою структуру данных одно и то же значение (дескриптор файла).

'skai.txt' => [
               \*{'::$fh'},
               $VAR1->{'skai.txt'}[0],
               $VAR1->{'skai.txt'}[0],
               $VAR1->{'skai.txt'}[0]
             ],

Первое значение (\*{'::$fh'}) - просто Data :: Dumper, слегка усложненныйспособ сказать "ссылка на дескриптор файла, который хранится в $fh".Три последующих значения - это Data :: Dumper, говорящий «это значение, которое уже появляется в этой структуре данных, поэтому вместо того, чтобы записывать это значение снова, я просто покажу вам ссылку на существующее значение».

Я думаю, что если вы измените эту строку на:

push @{$data->{$arg}}, $_;

Тогда вы получите нечто намного ближе к тому, что вы хотели.

2 голосов
/ 21 марта 2019

Похоже, вам не нужны отдельные массивы с именами @first_array, @second_array и т. Д. Вы просто хотите хранить их отдельно.

В таком случае, почему бы просто не иметь массив массивов? Вот так:

my @array_of_arrays;

for my $f (@ARGV) {
   my @array = load_file($f);
   push @array_of_arrays, \@array;
}

Примечание: load_file - это просто заполнитель для некоторой функции, которую вы, вероятно, должны прочитать файл в массив.

Потом позже ...

array_of_arrays[0][0] * array_of_arrays[1][0] * ... * array_of_arrays[$N][0]

Обновление : вам нужно передать ссылку в @array в функцию push, а не просто @array. В противном случае push создаст плоский массив, содержащий все элементы каждого отдельного массива. Спасибо @Garo и @mob за указание на это.

1 голос
/ 21 марта 2019

Если я правильно понимаю ваш вопрос, то вам следует использовать ссылки на массивы внутри хеша, хэшрефа, массива или массива.

Ниже описано, как я это сделаю (хэш реферата arrayrefs):

my $data={};  #a hashref where all data will end up
foreach my $currentfile (@ARGV){
  open (my $filehandle ,$currentfile);
  $data->{$currentfile}=[];  #a empty arrayref inside the hashref for every file
  while(<$fh>) {
    push @{$data->{$currentfile}}; #add lines to the arrayref
  }
  close $filehandle;
}

Результат: все данные будут доступны в виде $data->{FILENAME}->[LINENUMBER COUNTING FROM 0].

Пример: строка 7 файла "foo.txt" теперь будет в $data->{foo.txt}->[6]

В зависимостидля вашей реальной цели массив или arrayref могут быть лучшим выбором, чем hashref (если вас не интересуют имена файлов, но вас интересует, какое количество аргументов они в @ARGV).Но это не совсем понятно в вашем вопросе

...