我循环遍历多行记录并将它们加载到数组中。我碰巧使用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'} = $1;
}
if($line =~ /marker-b:(.*)/){
# Update data object
$$record{'b'} = $1;
}
if($line =~ /eor/){
# End of record; add to data array
push(@$data,$record);
$record = {};
}
}
#Update leftover data to data array
push(@$data,$record);
有更好的方法吗?我知道我可以创建一个函数,但我正在寻找更优雅的东西。我还没有测试过这段代码,但它应该足以让我知道我在做什么。如果有任何问题,请告诉我。
答案 0 :(得分:3)
所以你想要在同一个地方处理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} = $1;
}
elsif ($line =~ /marker-b:(.*)/) {
$record->{b} = $1;
}
}
答案 1 :(得分:2)
所有必要的是改变
if ( $line =~ /eor/ )
到
if ( $line =~ /eor/ or eof )
并删除循环外的push
这是一个更完整的解决方案,它使用最佳实践并避免将空记录推送到阵列
my ($data, $record);
while ( <$file> ) {
if ( /marker-([ab]):(.*)/ ) {
$record->{$1} = $2;
}
if ( ( /eor/ or eof ) and $record ) {
push @$data, $record;
$record = undef;
}
}