【问题标题】:Perl matrix to hash conversionPerl 矩阵到哈希转换
【发布时间】:2014-03-28 21:39:54
【问题描述】:

我正在尝试将一个大矩阵(一个制表符分隔的文件,每列中的元素数量不同)转换为数组的散列。在第一步中,我成功加载文件并使用 Test::CSV 将数据的列转换为列表,但在此过程中,我注意到每个列表的长度是对应于较大列的元素数,即对于那些元素较少的列,存在一个空格。到目前为止,这是我的代码:

#!/usr/bin/perl
use warnings;
use strict;
use Text::CSV;

my $csv = Text::CSV->new({
    sep_char => "\t",
});

open( LIST, "<", "testfile" ) or die "No esta el archivo\n";

while (<LIST>) {
     if ($csv->parse($_)) {
    my   @columns = $csv->fields();
        print "$columns[0]\t$columns[1]\t$columns[2]","\n";
    } else {
        my $err = $csv->error_input;
    }
}
close(LIST);

输入矩阵有 20 列,4500-8500 行加上一个标题行(理想情况下,我想将其用作哈希中的键)。为简单起见,我构建了一个包含三列的“测试文件”,没有标题和不同数量的元素(与原始输入文件的格式相同)。下面是testfile的内容:

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

这是输出。我认为“使用未初始化的值...”与空格有关。

1  1  2
Use of uninitialized value in concatenation (.) or string at blast.cruce.especies.pl line 16, <LIST> line 3.
2  2  
  3  4
Use of uninitialized value in concatenation (.) or string at blast.cruce.especies.pl line 16, <LIST> line 5.
5  6  
Use of uninitialized value in concatenation (.) or string at blast.cruce.especies.pl line 16, <LIST> line 6.
6  7  
7  8  8
Use of uninitialized value in concatenation (.) or string at blast.cruce.especies.pl line 16, <LIST> line 8.
8  9  
Use of uninitialized value in concatenation (.) or string at blast.cruce.especies.pl line 16, <LIST> line 9.
Use of uninitialized value in concatenation (.) or string at blast.cruce.especies.pl line 16, <LIST> line 9.

【问题讨论】:

    标签: perl hash matrix


    【解决方案1】:

    您看到这些错误的原因是您正在输入类似于以下内容的行:

    \t\t1
    

    解析到列表:

    ( undef, undef, 1 )
    

    由于您将 0 宽度字符拉入该字段。问题不在于解析,而在于打印。如果您想在解析后检查内容,请使用 Data::Printer 或 Data::Dumper 格式化输出行,这不会给您提供 undef 值被插值的错误。

    编辑:您的代码是正确的:

    #!/usr/bin/perl
    use warnings;
    use strict;
    use Text::CSV;
    
    my $csv = Text::CSV->new({
      sep_char => ",",
      });
    
    while (<DATA>) {
            if ($csv->parse($_)) {
        my   @columns = $csv->fields();
              print "$columns[0]\t$columns[1]\t$columns[2]","\n";
              } else {
            my $err = $csv->error_input;
        }
    }
    
    
    __DATA__
    1,1,2
    2,2,
    ,3,4
    5,6,
    6,7,
    7,8,8
    8,9,
    

    打印:

    C:\>perl testcsv.pl
    1       1       2
    2       2
            3       4
    5       6
    6       7
    7       8       8
    8       9
    

    (更改只是从 DATA 句柄而不是文件中读取。)

    【讨论】:

    • 我会试试的。谢谢!!
    • 嗨,厄索尔。我仍然不尝试 Data::Printer 或 Dumper,但我将 testfile 中的制表符分隔符更改为逗号并将 sep_char 更改为“,”,现在我无法打印等于输入的矩阵。
    • 我编辑了我的帖子以表明您的代码在逗号分隔符下可以正常工作。
    • 不错的编辑。仅供参考,您必须确保在行尾有逗号,例如6,7,。否则@columns 将只有 2 个元素,$columns[2] 将是未定义的,你会得到同样的错误..
    • 感谢 Oesor 的帮助。你提到 \t\t1 让我大开眼界。
    【解决方案2】:

    这里又出现了一些问题。我将上面的代码简化为:

    #!/usr/bin/perl
    use warnings;
    use strict;
    use Text::CSV;
    use Data::Dumper;
    $Data::Dumper::Indent=0;
    
    my @columns;
    my %matrixhash;
    my $csv = Text::CSV->new( { sep_char => "," } );
    
    open( LIST, "<", "testfile.csv" ) or die "No esta el archivo\n";
    
    while (<LIST>) {
        if ( $csv->parse($_) ) {
            @columns = $csv->fields();
    
    %matrixhash=(
        a=>$columns[0],
        b=>$columns[1],
        c=>$columns[2]
    );
    }   
            print Dumper \@columns;
            print "\n";
    
    }
    print "Printing Hash: ",Dumper \%matrixhash;
    close(LIST);
    

    输出是:

    $VAR1 = ['1','1','2'];
    $VAR1 = ['2','2',''];
    $VAR1 = ['','3','4'];
    $VAR1 = ['5','6',''];
    $VAR1 = ['6','7',''];
    $VAR1 = ['7','8','8'];
    $VAR1 = ['8','9',''];
    $VAR1 = {'c' => '','a' => '8','b' => '9'};
    

    对应于我的矩阵的行,散列确实是最后一行。为了继续我的下游分析,我需要一个哈希集合,其中包含列标题作为键,矩阵中的列信息作为值,当然没有空格。例如,对于矩阵的第一列,哈希将为:a=> {1,2,5,6,7,8)。所以,我的第二个想法是,如果我转置矩阵会发生什么?:

    $VAR1 = ['1','2','','5','6','7','8'];
    $VAR1 = ['1','2','3','6','7','8','9'];
    $VAR1 = ['2','','4','','','8',''];
    Printing Hash: $VAR1 = {'c' => '4','a' => '2','b' => ''}
    

    这更接近我的需要,但仍然存在哈希问题。当然,我可能需要在代码中转置前面的矩阵(该示例被手动转置)。

    再次,欢迎所有帮助。 克里斯蒂安。

    【讨论】:

    • 您应该提出一个新问题作为一个新问题,而不是前一个问题的答案。不过,您正在寻找类似于 if (defined $columns[0]) { push @{$matrixhash{a}}, $columns[0] } 的东西,这将创建一个包含类似于 {a => [1, 2, 5, 6, 7, 8] } 的 arrayref 的哈希值
    • 哦。我不认为这个问题是新问题,因为最初的问题(“我正在尝试将一个大矩阵(每列中元素数量不同的制表符分隔文件转换为数组哈希”)仍然存在。但是你的正确,从脚本的角度来看是一个新问题。我的错误。我会按照你的指示并作为新问题发布。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2013-07-09
    • 2012-04-26
    • 2016-04-03
    • 2012-11-11
    • 2021-07-13
    • 1970-01-01
    • 2017-01-06
    • 2015-01-09
    相关资源
    最近更新 更多