Чтение чисел из файла в переменные (Perl) - PullRequest
1 голос
/ 01 августа 2011

Я пытался написать программу для чтения столбцов чисел в формате текста в переменные Perl.

По сути, у меня есть файл с описаниями и числами:

ref   5.25676      0.526231      6.325135
ref   1.76234     12.62341       9.1612345

и т. Д.

Я бы хотел поместить числа в переменные с разными именами, например

ref_1_x=5.25676
ref_1_y=0.526231

и т. Д.

Вот что я получил до сих пор:

print "Loading file ...";
open (FILE, "somefile.txt");
@text=<FILE>;
close FILE;
print "Done!\n";
my $count=0;
foreach $line (@text){
    @coord[$count]=split(/ +/, $line);
}

Я пытаюсь сравнить позиции, записанные в файле, друг с другом,поэтому потребуется еще один цикл после этого.

Ответы [ 2 ]

4 голосов
/ 01 августа 2011

Извините, вам не очень понятно, что вы пытаетесь сделать и что означает "ссылка".Если я неправильно понял вашу проблему, пожалуйста, оцените и уточните.


Прежде всего, я бы настоятельно рекомендовал не использовать переменную names для структурирования данных (например, $ref_1_x для хранения координаты x).для первой строки с меткой «ref»).

Если вы хотите сохранить координаты x, y и z, вы можете сделать это как массив из 3 элементов, почти так же, как вы сделали - единственное отличие состоит в том, чточто вы хотите сохранить массив ссылка (вы не можете сохранить массив как значение в другом массиве в Perl):

my ($first_column, @data) = split(/ +/, $line); # Remove first "ref" column
@coordinates[$count++] = \@data; # Store the reference to coordinate array

Затем, чтобы получить доступ к координате х для строки2, вы делаете:

$coordinates[1]->[0]; # index 1 for row 2; then sub-index 0 for x coordinate.

Если вы настаиваете на сохранении 3-х координат в именованной структуре данных, потому что sub-index 0 for x coordinate выглядит менее читабельным - что является действительной проблемой в целом, но на самом деле не является проблемойс 3 столбцами - используйте хеш вместо массива:

my ($first_column, @data) = split(/ +/, $line); # Remove first "ref" column
@coordinates[$count++] = { x => $data[0], y => $data[1], z => $data[2] };
# curly braces - {} - to store hash reference again

Затем, чтобы получить доступ к координате х для строки 2, вы делаете:

$coordinates[1]->{x}; # index 1 for row 2

Теперь, если выТАКЖЕ хочу хранить строки, которые имеют значение первого столбцаf "в отдельной структуре данных, помеченной" ref ", вы можете сделать это, обернув исходный массив @coordinates в значение в хэше с ключом" ref ".

my ($label, @data) = split(/ +/, $line); # Save first "ref" label
$coordinates{$label} ||= []; # Assign an empty array ref 
                          #if we did not create the array for a given label yet.
push @{ $coordinates{$label} }, { x => $data[0], y => $data[1], z => $data[2] };
# Since we don't want to bother counting per individual label, 
# Simply push the coordinate hash at the end of appropriate array.
# Since coordinate array is stored as an array reference, 
# we must dereference for push() to work using @{ MY_ARRAY_REF } syntax

Затем, чтобы получить доступ к координате x для строки 2 для метки «ref», выполните:

$label = "ref";
$coordinates{$label}->[1]->{x}; # index 1 for row 2 for $label

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

Вот слегка измененная версия:

use strict;
my %coordinates;
print "Loading file ...";
open (my $file, "<", "somefile.txt") || die "Can't read file somefile.txt: $!";
while (<$file>) {
    chomp;
    my ($label, @data) = split(/ +/); # Splitting $_ where while puts next line
    $coordinates{$label} ||= []; # Assign empty array ref if not yet assigned
    push @{ $coordinates{$label} }
       , { x => $data[0], y => $data[1], z => $data[2] };
}
close($file);
print "Done!\n";

Не ясно, с чем вы хотите сравнить, с чем, поэтому не могу посоветовать это без дополнительных разъяснений.

0 голосов
/ 01 августа 2011

Проблема в том, что вам, вероятно, нужен двойной массив (или хеш или ...). Вместо этого:

@coord[$count]=split(/ +/, $line);

Использование:

@coord[$count++]=[split(/ +/, $line)];

, который помещает все результаты разбиения в под массив Таким образом,

print $coord[0][1];

должно вывести «5.25676».

...