Perl 在“while”循环下向标量列表添加值
有人能解释一下,当我从csv文件中读取值时,如何向标量列表中添加值吗 代码如下:Perl 在“while”循环下向标量列表添加值,perl,csv,Perl,Csv,有人能解释一下,当我从csv文件中读取值时,如何向标量列表中添加值吗 代码如下: open (IN, $infile) || die "Cannot open $infile\n"; my ($x,$y); while (my $line = <IN>){ chomp ($line); my @temp = split (/,/,$line); $x .= $temp[0].","; $y .= $temp[1].","; } $x = [$x];
open (IN, $infile) || die "Cannot open $infile\n";
my ($x,$y);
while (my $line = <IN>){
chomp ($line);
my @temp = split (/,/,$line);
$x .= $temp[0].",";
$y .= $temp[1].",";
}
$x = [$x];
$y = [$y];
close (IN);
这确实有效,并将其放入列表中,但不是逐个值,而是将所有值合并为一个。您说的是列表,但您指的是数组。如果您从实际使用数组开始,它会有所帮助
my (@xs, @ys);
while (my $line = <IN>){
chomp ($line);
my ($x, $y) = split (/,/,$line);
push @xs, $x;
push @ys, $y;
}
my $xs = \@xs;
my $ys = \@ys;
稍微优雅一点;不需要用两个多余的变量将名称空间弄乱
my ($xs, $ys) = ([], []);
while(my $line = <IN>) { #Note: don't use bare filehandles like this. (See below)
chomp $line;
my ($x, $y) = split /,/, $line;
push @$xs, $x;
push @$ys, $y;
}
#done
裸文件句柄是个坏主意。使用词法文件句柄。和3-arg打开!。词法文件句柄超出范围时自动关闭。看
自Merijn Brand aka Tux最新发布以来,它确实允许使用中指定的文本/csv片段标识符。这使得获取csv文件的特定片段变得非常简单 这段代码现在非常简单:
use strict;
use warnings;
use Text::CSV_XS ('csv');
my $infile = 'foobar.csv';
my @column_1 = map {$_->[0]} @{ csv(in => $infile, fragment => 'col=1') };
my @column_2 = map {$_->[0]} @{ csv(in => $infile, fragment => 'col=2') };
csv函数返回对数组的引用。因此,map操作符需要解引用@{…}
对于那些不想执行OOP的用户,csv函数采用多个参数:
in=>
这将指定输入,在本例中为输入文件。不需要做所有的花哨的检查或处理文件句柄。一切都被处理掉了
片段=>
这将从以下选择器中选择一个:“行”、“列”或“单元格”以及一个范围
行=1;5-7;十,-*
意思是:第1行,然后是第5行到第7行,最后是从第10行到最后一行
col=2;8-12
平均值:第2列和第8列至第12列
单元格=3,4-8,15
返回12行6列的块,从单元格3,4第3列第4行开始
警告:在解析csv文件时,千万不要依靠自己的聪明才智,很多时候人们都会落入这个陷阱,直到后来才意识到有些列突然包含逗号本身。尽管西奥的答案非常完美,但它仍然会读取文件两次 使用电子表格::读取和隐藏文本::CSVxs更容易:
use Spreadsheet::Read;
my $ss = ReadData ("file.csv");
my @col1 = @{$ss->[1]{cell}[1]}; unshift @col1; # SS = 1-base [0] does not contain a cell
my @col2 = @{$ss->[1]{cell}[2]}; unshift @col2;
使用Text::csvxs,但只读取一次文件
use Text::CSV_XS qw( csv );
my $col_1_2 = csv (in => "file.csv", fragment => "col=1;2");
my @column_1 = map {$_->[0]} @$col_1_2;
my @column_2 = map {$_->[1]} @$col_1_2;
是的,我是这样开始的。我不知道使用\@array!谢谢实际上,它在同一个位置创建了同样多的中间数组。唯一更改的是在何处创建对这些数组的引用。您的选择会导致每个输入行增加两个不必要的取消引用。@ikegami过早优化是万恶之源。您说过,不必要的取消引用;我认为这意味着您反对微不足道的性能开销;你肯定不是因为清楚而反对他们吗?没错。建议避免使用最终都没有使用的中间数组不是你应该做的事情。@ikegami无论如何,我将解释重新表述为更清楚。我考虑任何中间变量,如果它只是用来生成引用,即使它不会导致内存中的内容重复。您可能想解释它是如何工作的。“fragment”是做什么的?csv返回的arrayref中有什么?我首先从fragment=>“cell=1,1-2,*”-但这不起作用,您可以使用RFC7111检查,看看我是否误解了它,或者它是否是一个bug。在那次尝试之后,我选择了单列选择。你是对的,你可以轻松;同时抓取两行。
use Text::CSV_XS qw( csv );
my $col_1_2 = csv (in => "file.csv", fragment => "col=1;2");
my @column_1 = map {$_->[0]} @$col_1_2;
my @column_2 = map {$_->[1]} @$col_1_2;