一个更好的变量命名系统?

B C*_*hen 2 perl foreach

编程的新手.任务是从字符串中提取特定数据,我选择编写如下代码 -

while ($line =<IN>) {
    chomp $line;
    @tmp=(split /\t/, $line); 
    next if ($tmp[0] !~ /ch/); 
    @tgt1=@tmp[8..11];
    @tgt2=@tmp[12..14];
    @tgt3=@tmp[15..17];
    @tgt4=@tmp[18..21];
    foreach (1..4) {
            print @tgt($_), "\n";
            }
Run Code Online (Sandbox Code Playgroud)

我认为@tgt($_)会被解释为@tgt1, @tgt2, @tgt3, @tgt4但我仍然得到@tgt一个全局符号的错误消息(@ tgt1,@ tgt2,@ tgt3,@ tgt4`已被声明).

Q1.我是否误解了foreach循环?

Q2.为什么perl看不到@tgt($_)@ tgt1,@ tgt2 ..etc?

Q2.根据经验,这可能是命名变量的一种不好的方法.命名具有相似特征的变量的首选方法是什么?

DVK*_*DVK 7

  • Q2.为什么perl不能将@tgt($ _)视为@ tgt1,@ tgt2 ..etc?

  • Q2.根据经验,这可能是命名变量的一种不好的方法.命名具有相似特征的变量的首选方法是什么?

我会一起回答.

@tgt($_) 并不意味着你希望它意味着什么

  • 首先,它是一个无效的语法(你不能在数组名后使用(),perl interpeter会产生编译错误).

  • 你要做的是通过一个表达式访问一个变量来访问不同的变量,从而得到它的名字(也就是符号引用).这是可能的; 但通常是一个坏主意和糟糕的Perl(因为,你可以,但你不应该这样做,没有一个非常好的理由).

  • 要以您尝试的方式访问元素$ _,请使用@{"tgt$_"}语法.但我再说一遍 - 不要这样做,即使你可以.

  • 一个正确的惯用解决方案:使用一个arrayrefs数组,你的1-4(或更确切地说是0-3)索引外部数组:

     # Old bad code: @tgt1=@tmp[8..11];
    
     # New correct code:
     $tgt[0]=[ @tmp[8..11] ]; # [] creates an array reference from a list.
     # etc... repeat 4 times - you can even do it in a smart loop later.
    
    Run Code Online (Sandbox Code Playgroud)

    这样做,它将对数组切片的引用存储到单个@tgt数组的第0个元素中.

    最后,@tgt数组有4个元素,每个元素都是对包含其中一个片的数组的数组引用.


  • Q1.我是否误解了foreach循环?

你的foreach循环(与其内容相反 - 见上文)是正确的,有一种风格警告 - 再次,当你可以使用默认$_变量时,你几乎不应该使用它,而是总是使用命名变量来提高可读性.

您可以按如下方式打印上述arrayrefs数组(如果任何语法不清楚,请单独询问 - 这是一个中级数据结构处理,而不是初学者):

foreach my $index (0..3) { 
    print join(",", @{ $tgt[$index]}) . "\n";
}
Run Code Online (Sandbox Code Playgroud)