从文件读取数字到变量 (Perl)

发布于 2024-11-27 05:19:44 字数 561 浏览 1 评论 0原文

我一直在尝试编写一个程序来将文本格式的数字列读入 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);
}

我正在尝试比较中写入的位置相互文件,因此在此之后需要另一个循环。

I've been trying to write a program to read columns of text-formatted numbers into Perl variables.

Basically, I have a file with descriptions and numbers:

ref   5.25676      0.526231      6.325135
ref   1.76234     12.62341       9.1612345

etc.

I'd like to put the numbers into variables with different names, e.g.

ref_1_x=5.25676
ref_1_y=0.526231

etc.

Here's what I've got so far:

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

I'm trying to compare the positions written in the file to each other, so will need another loop after this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

疯了 2024-12-04 05:19:44

抱歉,您不太清楚您要做什么以及“ref”指的是什么。如果我误解了您的问题,请赞扬并澄清。


首先,我强烈建议不要使用变量名称来构造数据(例如使用$ref_1_x来存储带有标签“ref”的第一行的x坐标)。

如果您想存储 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 行的 x 坐标,您可以执行以下操作:

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

如果您坚持将 3 个坐标存储在命名数据结构中,因为 子索引0 表示 x 坐标 看起来可读性较差 -一般来说,这是一个有效的问题,但对于 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 行的 x 坐标,您可以:

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

现在,如果您还想存储具有在单独的“ref”标记数据结构中的第一列值“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

然后,要访问标签“ref”第 2 行的 x 坐标,您可以执行以下操作:

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

另外,您的原始示例代码有一些过时的习惯用法,您可能希望以更好的风格编写它们(使用 3 参数形式的 open(),检查 IO 操作上的错误,例如 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";

尚不清楚您想要与什么进行比较,因此在没有进一步说明的情况下无法就此提供建议。

Sorry, you weren't terribly clear on what you're trying to do and what "ref" refers to. If I misunderstood your problem please commend and clarify.


First of all, I would strongly recommend against using variable names to structure data (e.g. using $ref_1_x to store x coordinate for the first row with label "ref").

If you want to store x, y and z coordinates, you can do so as an array of 3 elements, pretty much like you did - the only difference is that you want to store an array reference (you can't store an array as a value in another array in Perl):

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

Then, to access the x coordinate for row 2, you do:

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

If you insist on storing the 3 coordinates in named data structure, because sub-index 0 for x coordinate looks less readable - which is a valid concern in general but not really an issue with 3 columns - use a hash instead of array:

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

Then, to access the x coordinate for row 2, you do:

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

Now, if you ALSO want to store the rows that have a first column value "ref" in a separate "ref"-labelled data structure, you can do that by wrapping the original @coordinates array into being a value in a hash with a key of "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

Then, to access the x coordinate for row 2 for label "ref", you do:

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

Also, your original example code has a couple of outdated idioms that you may want to write in a better style (use 3-argument form of open(), check for errors on IO operations like open(); use of lexical filehandles; storing entire file in a big array instead of reading line by line).

Here's a slightly modified version:

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";

It is not clear what you want to compare to what, so can't advise on that without further clarifications.

苦妄 2024-12-04 05:19:44

问题是您可能需要一个双数组(或散列或...)。而不是这样:

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

使用:

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

将拆分的整个结果放入子数组中。因此,

print $coord[0][1];

应该输出“5.25676”。

The problem is you likely need a double-array (or hash or ...). Instead of this:

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

Use:

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

Which puts the entire results of the split into a sub array. Thus,

print $coord[0][1];

should output "5.25676".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文