如何从Perl中的标准输入构建2D矩阵?

时间:2009-10-19 02:54:05

标签: perl arrays matrix 2d

好吧,整个周末我一直都在苦苦挣扎,而且我得到了很多帮助,但我仍然没有得到它。到目前为止,这是我的代码:我想要做的是从用户输入构建一些矩阵。最终我想要倍增它们。另一个故事。

输入如下

1 2 2 4
4 5 6 6

1 2 2 3
1 2 2 3

sub makeMatrix {
  my ($input) = @_;
  my @mat;
  while (<$input>) {
    if ($input eq ""){
        print "it's blank\n";
        return;
    }
    else{
        push @mat, [ split ];
    }
    return \@mat;
    }
}

my @a = ();
while($a = <>) {
    chomp $a;
    push @a,($a);
    }


@matrices;
push @mat, (makeMatrix(@a));

foreach $input (@matrices){
    print "input was $input\n";

}

为什么这不起作用?为什么它不在@matrices中创建矩阵数组?它是子程序中的return语句吗?我的目标是在矩阵数组中有两个矩阵。谢谢你的帮助。

3 个答案:

答案 0 :(得分:2)

你似乎对&lt;&gt;的含义感到有点困惑。操作

该行

while (<$input>)

错了。这告诉Perl从文件句柄$input读取。但是,传递给子例程的不是文件句柄,而是一段文本。你不需要&lt;&gt;这里。而且,您似乎已经丢弃了子程序的大部分输入。你这样称呼它:

makeMatrix(@a)

但是你只能在例程中使用@a的第一个值。例程应如下所示:

use warnings;
use strict;

sub makeMatrix {
    my @inputs = @_;
    my @mat;
    for my $input (@inputs) {
        # print "$input\n"; # debugging code left here for artistic effect
        if ($input eq "") {
            print "it's blank\n";
        }
        else{
            push @mat, [ split /\s+/, $input ];
        }
    }
    return \@mat;
}

my @a;

while ($a = <>) {
    chomp $a;
    push @a, $a;
}


my $matrices = makeMatrix (@a);

for my $row (@$matrices){
    for my $column (@$row) {
        print "input was $column\n";
    }
}

答案 1 :(得分:1)

你传递makeMatrix一个字符串数组,但该函数假装传递了一个文件句柄。

我不知道为什么你会跳过这么多箍,但这是你的代码的大问题。

此外, 如果将真正的文件句柄传递给makeMatrix ,那么该行

while (<$input>) {
   if ($input eq ""){

不会做你认为它应该做的事情。

while (<$input>) {

会在每次迭代时将行读入$_。所以:

   if ($input eq ""){

将始终为false,因为$input将是一个文件句柄(因此不等于空字符串)。此外,即使你写得正确

   if ($_ eq ""){

遇到空行时条件为false,因为你没有chomp离开行结束($_不为空)。

总而言之,这是一个名副其实的代码,读者只能尝试猜测你正在尝试做什么。想想你想要完成什么,并解释它好一点。

http://learn.perl.org/有很多学习Perl的资源。

以下代码非常模糊,我不建议将它用于制作,但试图找出它的作用可能会教你很多:

#!/usr/bin/perl

use strict;
use warnings;

use Data::Dumper;

while ( my $matrix = read_matrix() ) {
    print Dumper $matrix;
}

sub read_matrix {
    local $/ = "\n\n";
    return if eof DATA;
    return [ map { [ split ] } split /\n/, scalar <DATA> ];
}

__DATA__
1 2 2 4
4 5 6 6

1 2 2 3
1 2 2 3

输出:

$VAR1 = [
          [
            '1',
            '2',
            '2',
            '4'
          ],
          [
            '4',
            '5',
            '6',
            '6'
          ]
        ];
$VAR1 = [
          [
            '1',
            '2',
            '2',
            '3'
          ],
          [
            '1',
            '2',
            '2',
            '3'
          ]
        ];

答案 2 :(得分:1)

马特,请检查我下面写的内容,看看我是否理解了这个问题:

我的一般观点是:

(1)您的示例数据不适用于矩阵乘法。如果你的第一个数组是2x4,那么你的第二个数组必须是4x2,你的答案是2x2。

(2)Perl为您提供了非常强大的数据语言(PDL),可以有效地进行矩阵操作。如果你打算做很多矩阵代数,我建议你使用它。

(3)根据下面的解决方案,只要您已将数据首先读入2D阵列(AoA是阵列数组),矩阵产品就会在3行中退出。

#!/usr/bin/perl
use strict;
use warnings;
use PDL; # perl data language enables matrix multiplication
use Inline::Files; #multiple virtual files inside code

my @AoA_A = make_matrix("ARRAY_A"); #read in 2D array
my @AoA_B = make_matrix("ARRAY_B");

my $a = pdl [ @AoA_A ]; #Construct new pdl object
my $b = pdl [ @AoA_B ];
my $c = $a x $b;  # x overload
print "matrix a", $a;
print "matrix b", $b;
print "matrix c",$c;

sub make_matrix {
    my $source = shift;
    my @AoA;
    while (<$source>){
        my @tmp = split;
        push @AoA, [ @tmp ];
    }
    return @AoA;  
}

__ARRAY_A__
1 2 2 4
4 5 6 6
__ARRAY_B__
1 2
2 3
1 2
2 3

它创建了以下输出:

matrix a
[
 [1 2 2 4]
 [4 5 6 6]
]
matrix b
[
 [1 2]
 [2 3]
 [1 2]
 [2 3]
]
matrix c
[
 [15 24]
 [32 53]
]