读取CSV文件并保存到二维数组中。

5
我正在尝试读取一个巨大的CSV文件并将其保存在二维数组中,一定有更好的方法可以在一步中拆分行并将其保存在二维数组中:s 干杯
my $j = 0;
while (<IN>) 
{

    chomp ;
    my @cols=();
    @cols   = split(/,/); 
    shift(@cols) ; #to remove the first number which is a line header
    for(my $i=0; $i<11; $i++) 
    {
       $array[$i][$j]  = $cols[$i];
    }        
    $j++;    
}

2
文件中的值是什么类型?如果有字符串(可能带引号等),最好使用Text::CSV模块。如果它们是纯数字,则可以使用简单的拆分,如所示。 - Jonathan Leffler
你是故意将行作为数组的第二个索引还是打错字/犯了错误? - Michael Carman
3个回答

12

CSV并不是简单的东西。不要自己解析它。使用像Text::CSV这样的模块,可以正确而快速地完成。

use strict;
use warnings;

use Text::CSV;

my @data;   # 2D array for CSV data
my $file = 'something.csv';

my $csv = Text::CSV->new;
open my $fh, '<', $file or die "Could not open $file: $!";

while( my $row = $csv->getline( $fh ) ) { 
    shift @$row;        # throw away first value
    push @data, $row;
}

这将使所有行都很好地放在@data中,无需担心自己解析CSV。


3

如果你发现自己需要使用C风格的for循环,那么你的程序设计很可能需要改进。

while (<IN>) {
    chomp;

    my @cols = split(/,/); 
    shift(@cols); #to remove the first number which is a line header

    push @array, \@cols;
}

假设您有一个CSV文件,可以使用简单的 split 进行处理(即记录不包含嵌入逗号)。

2

另外:您可以使用以下方式简化您的代码:

my @cols = split /,/;

你对 $array[$col][$row] 的赋值使用了不寻常的下标顺序,这使得问题变得复杂了。 根据你在数组中列/行的赋值顺序,我认为没有更简单的方法来处理它。


替代方案: 如果你能反转数组下标的顺序($array[$row][$col]),你可以考虑使用:

use strict;
use warnings;

my @array;
for (my $j = 0; <>; $j++) # For testing I used <> instead of <IN>
{
    chomp;
    $array[$j] = [ split /,/ ];
    shift @{$array[$j]};   # Remove the line label
}

for (my $i = 0; $i < scalar(@array); $i++)
{
    for (my $j = 0; $j < scalar(@{$array[$i]}); $j++)
    {
        print "array[$i,$j] = $array[$i][$j]\n";
    }
}

示例数据

label1,1,2,3
label2,3,2,1
label3,2,3,1

样例输出

array[0,0] = 1
array[0,1] = 2
array[0,2] = 3
array[1,0] = 3
array[1,1] = 2
array[1,2] = 1
array[2,0] = 2
array[2,1] = 3
array[2,2] = 1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接