Perl 在“while”循环下向标量列表添加值

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];

有人能解释一下,当我从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];
$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;