如果 $returnintersection 为真,我编写了以下 perl 代码来为任何两个输入列表返回一个类似交集的列表。否则,它将返回任何一个公共元素,如果没有,则返回 0。
通过类似交叉点,我指的是通配符匹配 - 一个列表中的 123* 将匹配另一个列表中的 12345。
这是输入和相应输出的示例。
getintersection (
['123*', '999', 'V890', '871'],
['10001', '8789', '999', '1234', 'V89*'],
1
)
will return
('999', 'V890', '1234')
我想知道我是否可以以一种表现更好的方式编写它?我敢肯定,ere 算法并不是最好的。任何有助于降低其复杂性的东西都将不胜感激!它的性能至关重要,因为它是一个非常常见的例程。(性能 => 速度,假设任一列表都可以包含 1 到 3000 个元素)
代码 -
sub getintersection {
my ($l1, $l2, $returnintersection) = @_;
if (!$l1 || !$l2) {
return $returnintersection ? undef : 0;
}
my ($small, $large);
if (scalar @$l1 > scalar @$l2 ) {
($small, $large) = ($l2, $l1);
}
else {
($small, $large) = ($l1, $l2);
}
my (%lhash, %l_starred, %s_starred, @intersection);
foreach my $l (@$large) {
$lhash{$l} = 1;
if ($l =~ m/^(.+)\*$/) {
$l_starred{$1} = 1;
}
}
foreach my $s (@$small) {
if ($lhash{$s}) {
return $s if (!$returnintersection);
push @intersection, $s;
}
else {
foreach my $k (keys %l_starred) {
if ($s =~ /^$k/) {
return $s if (!$returnintersection);
push @intersection, $s;
}
}
}
if ($s =~ m/^(.+)\*$/) {
$s_starred{$s} = 1;
}
}
foreach my $s (keys %s_starred) {
foreach my $l (@$large) {
if ($l =~ /^$s/) {
return $l if (!$returnintersection);
push @intersection, $l;
}
}
}
return $returnintersection ? @intersection : scalar @intersection;
}