在检测 EOR 与 EOF 时删除代码重复

Removing code duplication in detecting EOR vs EOF

我正在遍历多行记录并将它们加载到一个数组中。我碰巧正在使用 Perl ,但语言无关紧要,因为我正在寻找算法的优化。具体来说,我对我正在编写数组推送两次这一事实感到困扰。当我找到记录结尾 (eor) 时进入循环,当我 运行 超出文件时再次进入循环(eof,而不是 eor)。我知道这不会影响速度,我只是不喜欢在两个地方重复代码。就是说如果改了,我得修改两个地方。

我采用的方法是:

my $data = []; #data object array
my $record = {};
my $line;
while (my $line = <$file>){
    if($line =~ /marker-a:(.*)/){
        # Update data object
        $$record{'a'} = ;
    }
    if($line =~ /marker-b:(.*)/){
        # Update data object
        $$record{'b'} = ;
    }
    if($line =~ /eor/){
        # End of record; add to data array
        push(@$data,$record);
        $record = {};
    }
}
#Update leftover data to data array
push(@$data,$record);

有更好的方法吗?我知道我可以创建一个函数,但我正在寻找更优雅的东西。我没有测试过这段代码,但它应该足以让我了解我在做什么。如果有任何问题,请告诉我。

因此您希望在同一个地方处理 EOR 和 EOF。这意味着检查 EOF 不能再在循环的顶部完成。将条件移动到循环中的技巧是切换到无限循环。

my $data = [];
my $record = {};
while (1) {
    my $line = <$file>;
    if (!defined($line) || $line =~ /eor/) {
        push(@$data, $record) if keys(%$record);
        last if !defined($line);
        $record = {};
    }
    elsif ($line =~ /marker-a:(.*)/) {
        $record->{a} = ;
    }
    elsif ($line =~ /marker-b:(.*)/) {
        $record->{b} = ;
    }
}

只需要改变

if ( $line =~ /eor/ )

if ( $line =~ /eor/ or eof )

并删除循环外的push


更新

这是一个更完整的解决方案,它使用最佳实践并避免将空记录推入数组

my ($data, $record);

while ( <$file> ) {

    if ( /marker-([ab]):(.*)/ ) {
        $record->{} = ;
    }

    if ( ( /eor/ or eof ) and $record ) {
        push @$data, $record;
        $record = undef;
    }
}