按下数组直到某个值

时间:2017-10-14 20:37:20

标签: arrays perl

说我循环浏览一些包含标题行的数据文件。例如,

[[1],[2],[3],[4],[5],[6],[7],[8],[9],[10]]

我想将所有标题行推送到>Header 1 data1 data2 data3 >Header 2 data4 data5 data6 >Header 3 数组,然后推送@headers数组中的所有数据。该关系应为1:1,即@data的第一个元素是">标题1" @headers的第一个元素是" data1data2data3"。我怎么能做到这一点?到目前为止,我有

@data

将每行数据放入my @data; my @headers; while(<$fh>){ chomp($_); if($_ =~ /(>)/){ push @headers, $_; } else{ push @data, $_; } } 中自己的索引中。基本上,如果该行以&#34;&gt;&#34;开头将其推送到@data数组,否则只要下一行不以&#34;&gt;&#34;开头,就将其推送到@headers数组。不太确定如何编写最后一部分。

2 个答案:

答案 0 :(得分:1)

当没有标题时,您不需要push@data。那会增加一个新元素。你想要做的是追加到最后一个元素。 Perl允许您使用索引[-1]来获取数组的最后一个元素。因此,您可以在向@data添加新元素的同时轻松地向@headers添加新元素,因为它们对应。

use strict;
use warnings;

my (@headers, @data);

while (<DATA>) {
    chomp; # no need for $_ here

    if ( m/^>/ ) { # no need for $_ here either
        push @headers, $_;
        push @data, q{}; # the empty string
    } else {
        $data[-1] .= $_;
    }
}

__DATA__
>Header 1
data1
data2
data3
>Header 2
data4
data5
data6
>Header 3

这会产生这些数据结构(用Data::Printer输出)。

[
    [0] ">Header 1",
    [1] ">Header 2",
    [2] ">Header 3"
]
[
    [0] "data1data2data3",
    [1] "data4data5data6",
    [2] ""
]

请注意,在大多数情况下,您不需要明确使用$_,因为如果没有其他内容,许多运营商会默认使用它们。在括号内的模式中,您也不需要捕获组()。您没有使用$1,因此浪费了资源。

答案 1 :(得分:0)

按照您的编码,我们可以:

my (@data, @headers, @sequences);

while( <$fh> ) {
  chomp($_);

  if( $_ =~ /(>)/ ) {
    push @headers, $_;
    push @data, join @sequences;
    @sequences = ();
  }
  else { 
    push @sequences, $_;   
  }
}
push @data, join @sequences;

每次找到新标题时,都会累积数据并重新开始序列。在循环结束时,您需要执行 final accummulation。

另请注意@simbabque评论不需要对大多数内置插件使用$_。我没有更改代码以避免混淆。