【问题标题】:Possible to assign count to array? like @content.$i?可以将计数分配给数组吗?像@content.$i?
【发布时间】:2016-08-05 08:31:44
【问题描述】:

我的 csv 输入文件

Chapter,Content
A,1
B,3
C,1
C,2
C,3
D,5

我当前的 perl 脚本

open(INFILE,$input)||die "can't open the file";
@line = (split/,/,$_);
@line_last = (split/\n/,$line[1]);
    if ($_ =~ /A/){
        push @con1, $line[1];
}
elsif ($_ =~ /B/){
    push @con2, $line[1];
}
elsif ($_ =~ /C/){
    push @con3, $line[1];
}
elsif ($_ =~ /D/){
    push @con4, $line[1];
}
close INFILE;

chomp @con1, @con2, @con3, @con4;
print "content =", (join ", ", @con1),"\n";
print "content =", (join ", ", @con2),"\n";
print "content =", (join ", ", @con3),"\n";
print "content =", (join ", ", @con4),"\n";

我当前的代码可以运行,但我想让我的代码更短、更高效。 如何使@con 更加自动化?类似于使用 For 循环并使用 $i 分配给 @con 以缩短整体代码。

【问题讨论】:

  • 你能提供一个正确输出的样本吗?此外,$input 没有在任何地方声明,所以这段代码不会运行。您还(可能)缺少像 while (<INFILE>) { 这样的行 - 没有它 $_ 将不会被定义,@line 中也不会出现任何内容 ...
  • $input = "testing.csv";输出:1 3 1,2,3 5
  • 错字
    我的脚本中有 $input & while ()
    $input = "testing.csv"; while (){ 输出:1 3 1,2,3 5

标签: arrays perl for-loop scalar


【解决方案1】:

Why it's stupid to `use a variable as a variable name'.

您应该改用 AoA。

use Text::CSV_XS qw( ); 

my $csv = Text::CSV_XS->new({ binary => 1, auto_diag => 2 });

open my $fh, "<", $qfn)
   or die("Can't open \"$qfn\": $!\n");

my @foos = qw( A B C D );
my $num_eles = 0;
my %index_by_foo = map { $_ => $num_eles++ } @foos;
my @cons_by_foo = map { [] } 1..$num_eles;

while (my $row = $csv->getline($fh)) {
   if ( my $i = $index_by_foo{ $row->[0] } ) {
      push @{ $cons_by_foo[$i] }, $row->[1];
   }
}

for my $i (1..$num_eles-1) {
   print("content =", join(", ", @{ $cons_by_foo[$i] }), "\n");
}

也就是说,HoA 似乎更合适。

use Text::CSV_XS qw( ); 

my $csv = Text::CSV_XS->new({ binary => 1, auto_diag => 2 });

open my $fh, "<", $qfn)
   or die("Can't open \"$qfn\": $!\n");

my %cons_by_foo;
while (my $row = $csv->getline($fh)) {
   push @{ $cons_by_foo{ $row->[0] } }, $row->[1];
}

for my $foo (sort keys %cons_by_foo) {
   print("content $foo =", join(", ", @{ $cons_by_foo{$foo} }), "\n");
}

【讨论】:

    【解决方案2】:

    这就是哈希对 IMO 的好处(哈希表或其他语言的字典)。

    注意:我没有测试过这段代码,它来自内存。

    my %con;
    while (<INFILE>)
    {
        my @line_last = (split/\n/,$line[1]);
        $con{$line[0]} = $con{$line[0]} + ", " +  $line[1];
    } 
    foreach my $str (keys sort %con)
    {
        print "content $con{$str}\n";
    }
    

    编辑:这里有更好且经过测试的代码。

    open(INFILE,"input.txt")||die "can't open the file";
    
    my %con;
    while (<INFILE>)
    {
        next if /^Chapter/;
        chomp;
        my @line = (split ',' , $_);
        push @{$con{$line[0]}}, $line[1];
    } 
    foreach my $str (sort keys %con)
    {
        my $tmp = join ', ', @{$con{$str}};
        print "content $str = $tmp\n";
    }
    

    输出是:

    content A = 1
    content B = 3
    content C = 1,2,3
    content D = 5
    

    我知道这不是你的输出,但它似乎比你的输出更有用。

    【讨论】:

    • 这会发出警告,这会导致输出中出现虚假逗号。 /// 我也认为将输出代码与输入代码混合是一个坏主意。它使修改程序变得更加困难(并将目录引向我提到的第二个问题)。
    • 你的 Perl 肯定更好,我对我的警告并不感到惊讶,我懒得在家里把它放在 Perl 中。我猜它警告 $con{$line[0]} 可能是未定义的还是什么?是的,我可能永远不会在生产代码中这样做,你的要好得多。
    • 是的,未定义的$con{$line[0]} 第一次遇到$line[0]
    • 所以,我是新来的。既然你有一个更好的解决方案(基本上是相同的解决方案,我会重写我的解决方案,而不是把它一起破解,一个 HoA),我应该删除我的答案还是只是编辑以说明你的答案更好并且一个 HoA 是方式去,我懒惰地实现它?
    • 一般来说,因为我没有机会真正查看任何一个答案:如果您认为您的答案添加了其他答案中没有的有价值的东西,或者您可以编辑它以添加有价值的东西,留着吧。如果它没有添加任何有价值的东西,请将其删除。如果你的答案只是说另一个答案是最好的解决方案,我认为这不是很有价值。
    【解决方案3】:
    my %cc;  #chapter contents
    open my $FH, $filename or die "Cannot open $filename";
    push @{ $cc{ $$_[0] } }, $$_[1] for map {chomp;[split/,/]} <$FH>;
    close $FH;
    print "Chapter = $_     Content = " . join(", ", @{ $cc{$_} }) . "\n" for sort keys %cc;
    

    输出:

    Chapter = A     Content = 1
    Chapter = B     Content = 3
    Chapter = C     Content = 1, 2, 3
    Chapter = D     Content = 5
    

    【讨论】:

      猜你喜欢
      • 2011-12-18
      • 1970-01-01
      • 1970-01-01
      • 2018-07-30
      • 1970-01-01
      • 2013-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多