如何在 Perl 中创建二维数组?

发布于 2024-09-27 14:49:00 字数 504 浏览 1 评论 0原文

我目前正在尝试将 32 x 48 矩阵文件传递到 Perl 中的多维数组。我可以访问所有值,但在访问特定值时遇到问题。

这是数据集的链接: http://paste-it.net/public/x1d5301/

这是我所拥有的现在就获取代码。

#!/usr/bin/perl

open FILE, "testset.txt" or die $!;
my @lines = <FILE>;

my $size = scalar @lines;

my @matrix = (1 .. 32);
my $i = 0;
my $j = 0;
my @micro;

foreach ($matrix)
{
    foreach ($lines)
    {
        push @{$micro[$matrix]}, $lines;
    }
}

I am currently trying to pass a 32 by 48 matrix file to a multi-dimensional array in Perl. I am able to access all of the values, but I am having issues accessing a specific value.

Here is a link to the data set:
http://paste-it.net/public/x1d5301/

Here is what I have for code right now.

#!/usr/bin/perl

open FILE, "testset.txt" or die $!;
my @lines = <FILE>;

my $size = scalar @lines;

my @matrix = (1 .. 32);
my $i = 0;
my $j = 0;
my @micro;

foreach ($matrix)
{
    foreach ($lines)
    {
        push @{$micro[$matrix]}, $lines;
    }
}

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

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

发布评论

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

评论(5

若水般的淡然安静女子 2024-10-04 14:49:00

您似乎不明白 $matrix 仅在紧随其后的是数组索引器时表示 @matrix[ $slot ]。否则,$matrix 是与@matrix 完全不同的变量(也与%matrix 不同)。请参阅 perldata

#!/usr/bin/perl
use English;

不要!使用英语——那样

这会引入 $MATCH$PREMATCH$POSTMATCH 并引发可怕的 $&、$` , $' 罚分。您应该等到使用一个英文变量,然后导入它。

open FILE, "testset.txt" or die $!;

两件事:1)使用 词汇 文件句柄,以及 2) 使用三参数 <代码>打开

my @lines = <FILE>;

只要我选择:不要吞食大文件。 (这里不是这种情况,但这是一个很好的警告。)

my $size = scalar @lines;

my @matrix = (1 .. 32);
my $i = 0;
my $j = 0;
my @micro;

我看到我们正处于 “PROFIT!!” 在此阶段...

foreach ($matrix) {

您没有变量 $matrix;你有一个变量@matrix

    foreach ($lines) {

$lines 也是如此。

        push @{ $micro[$matrix]}, $lines;
    }
}

改写:

use strict;
use warnings;
use English qw<$OS_ERROR>; # $!
open( my $input, '<', 'testset.txt' ) or die $OS_ERROR;

# I'm going to assume space-delimited, since you don't show
my @matrix;
# while ( defined( $_ = <$input> ))...
while ( <$input> ) {
    chomp; # strip off the record separator
    # Load each slot of @matrix with a reference to an array filled with
    # the line split by spaces.
    push @matrix, [ split ]; # split = split( ' ', $_ )
}

It doesn't seem you understand that $matrix only indicates @matrix when it is immediately followed by an array indexer: [ $slot ]. Otherwise, $matrix is a completely different variable from @matrix (and both different from %matrix as well). See perldata.

#!/usr/bin/perl
use English;

Don't! use English--that way!

This brings in $MATCH, $PREMATCH, and $POSTMATCH and incurs the dreaded $&, $`, $' penalty. You should wait until you're using an English variable and then just import that.

open FILE, "testset.txt" or die $!;

Two things: 1) use lexical file handles, and 2) use the three-argument open.

my @lines = <FILE>;

As long as I'm picking: Don't slurp big files. (Not the case here, but it's a good warning.)

my $size = scalar @lines;

my @matrix = (1 .. 32);
my $i = 0;
my $j = 0;
my @micro;

I see we're at the "PROFIT!!" stage here...

foreach ($matrix) {

You don't have a variable $matrix; you have a variable @matrix.

    foreach ($lines) {

The same thing is true with $lines.

        push @{ $micro[$matrix]}, $lines;
    }
}

Rewrite:

use strict;
use warnings;
use English qw<$OS_ERROR>; # $!
open( my $input, '<', 'testset.txt' ) or die $OS_ERROR;

# I'm going to assume space-delimited, since you don't show
my @matrix;
# while ( defined( $_ = <$input> ))...
while ( <$input> ) {
    chomp; # strip off the record separator
    # Load each slot of @matrix with a reference to an array filled with
    # the line split by spaces.
    push @matrix, [ split ]; # split = split( ' ', $_ )
}
安穩 2024-10-04 14:49:00

如果您要做大量数学运算,您可以考虑 PDL(Perl 数据语言)。您可以轻松地设置矩阵并在对其进行操作之前:

use 5.010;

use PDL;
use PDL::Matrix;

my @rows;
while( <DATA> ) {
    chomp;
    my @row = split /\s+/;
    push @rows, \@row;
    }

my $a = PDL::Matrix->pdl( \@rows );
say "Start ", $a;

$a->index2d( 1, 2 ) .= 999;
say "(1,2) to 999 ", $a;

$a++;
say "Increment all ", $a;

__DATA__
1 2 3
4 5 6
7 8 9
2 3 4

输出显示了矩阵的演变:

Start 
[
 [1 2 3]
 [4 5 6]
 [7 8 9]
 [2 3 4]
]

(1,2) to 999 
[
 [  1   2   3]
 [  4   5 999]
 [  7   8   9]
 [  2   3   4]
]

Increment all 
[
 [   2    3    4]
 [   5    6 1000]
 [   8    9   10]
 [   3    4    5]
]

有相当大的能力可以对矩阵的每个成员运行任意和复杂的操作,就像我向每个成员添加 1 一样。你完全跳过了循环杂技。

不仅如此,PDL 还做了很多特殊的事情来使数学运算变得非常快并且内存占用很小。您想做的一些事情可能已经实现了。

If you are going to be doing quite a bit of math, you might consider PDL (the Perl Data Language). You can easily set up your matrix and before operations on it:

use 5.010;

use PDL;
use PDL::Matrix;

my @rows;
while( <DATA> ) {
    chomp;
    my @row = split /\s+/;
    push @rows, \@row;
    }

my $a = PDL::Matrix->pdl( \@rows );
say "Start ", $a;

$a->index2d( 1, 2 ) .= 999;
say "(1,2) to 999 ", $a;

$a++;
say "Increment all ", $a;

__DATA__
1 2 3
4 5 6
7 8 9
2 3 4

The output shows the matrix evolution:

Start 
[
 [1 2 3]
 [4 5 6]
 [7 8 9]
 [2 3 4]
]

(1,2) to 999 
[
 [  1   2   3]
 [  4   5 999]
 [  7   8   9]
 [  2   3   4]
]

Increment all 
[
 [   2    3    4]
 [   5    6 1000]
 [   8    9   10]
 [   3    4    5]
]

There's quite a bit of power to run arbitrary and complex operations on every member of the matrix just like I added 1 to every member. You completely skip the looping acrobatics.

Not only that, PDL does a lot of special stuff to make math really fast and to have a low memory footprint. Some of the stuff you want to do may already be implemented.

缘字诀 2024-10-04 14:49:00

您可能需要 chomp 这些值:

chomp( my @lines = <FILE> );

You probably need to chomp the values:

chomp( my @lines = <FILE> );
单调的奢华 2024-10-04 14:49:00

澄清与Axeman的答案相切的一点

参见 perldoc -f split

/\s+/ 上的拆分类似于 split(' '),只不过任何前导空格都会生成空的第一个字段。不带参数的 split 实际上在内部执行了 split(' ', $_)

#!/usr/bin/perl

use YAML;

$_ = "\t1 2\n3\f4\r5\n";

print Dump { 'split'       => [ split       ] },
           { "split ' '"   => [ split ' '   ] },
           { 'split /\s+/' => [ split /\s+/ ] }
           ;

输出:

---
split:
  - 1
  - 2
  - 3
  - 4
  - 5
---
split ' ':
  - 1
  - 2
  - 3
  - 4
  - 5
---
split /\s+/:
  - ''
  - 1
  - 2
  - 3
  - 4
  - 5

To clarify a tangential point to Axeman's answer:

See perldoc -f split:

A split on /\s+/ is like a split(' ') except that any leading whitespace produces a null first field. A split with no arguments really does a split(' ', $_) internally.

#!/usr/bin/perl

use YAML;

$_ = "\t1 2\n3\f4\r5\n";

print Dump { 'split'       => [ split       ] },
           { "split ' '"   => [ split ' '   ] },
           { 'split /\s+/' => [ split /\s+/ ] }
           ;

Output:

---
split:
  - 1
  - 2
  - 3
  - 4
  - 5
---
split ' ':
  - 1
  - 2
  - 3
  - 4
  - 5
---
split /\s+/:
  - ''
  - 1
  - 2
  - 3
  - 4
  - 5
胡大本事 2024-10-04 14:49:00

我发现这个问题已经很老了,但由于作者刚刚编辑了这个问题,也许这仍然很有趣。此外,数据的链接已失效,但由于其他答案使用空格作为分隔符,我也会这样做。

这个答案演示了 Tie::Array::CSV允许随机访问 CSV(或其他可使用 Text::CSV 解析的文件一个>)。

#!/usr/bin/env perl

use strict;
use warnings;

use Tie::Array::CSV;

## put DATA into temporary file
## if not using DATA, put file name in $file
use File::Temp ();
my $file = File::Temp->new();
print $file <DATA>;
##


tie my @data, 'Tie::Array::CSV', $file, { 
  text_csv => {
    sep_char => " ",
  },
};

print $data[1][2];

__DATA__
1 2 3 4 5
6 7 8 9 1
2 3 4 5 6

I see the question is pretty old, but as the author has just edited the question, perhaps this is still of interest. Also the link to the data is dead, but since other answers use space as the separator, I will too.

This answer demonstrates Tie::Array::CSV which allows random access to a CSV (or other file parsable with Text::CSV).

#!/usr/bin/env perl

use strict;
use warnings;

use Tie::Array::CSV;

## put DATA into temporary file
## if not using DATA, put file name in $file
use File::Temp ();
my $file = File::Temp->new();
print $file <DATA>;
##


tie my @data, 'Tie::Array::CSV', $file, { 
  text_csv => {
    sep_char => " ",
  },
};

print $data[1][2];

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