在检测 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;
}
}
我正在遍历多行记录并将它们加载到一个数组中。我碰巧正在使用 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;
}
}