Bil*_*ill 51 arrays perl compare match
我有两个字符串数组,我想比较相等:
my @array1 = ("part1", "part2", "part3", "part4");
my @array2 = ("part1", "PART2", "part3", "part4");
Run Code Online (Sandbox Code Playgroud)
是否有内置的方法来比较数组,就像标量一样?我试过了:
if (@array1 == @array2) {...}
Run Code Online (Sandbox Code Playgroud)
但它只是在标量上下文中评估每个数组,因此比较了每个数组的长度.
我可以使用自己的函数来完成它,但它看起来像是一个低级操作,应该有一个内置的方法来做它.在那儿?
编辑:遗憾的是,我无法访问5.10+或可选组件.
Sin*_*nür 56
有一个新的智能匹配运营商:
#!/usr/bin/perl
use 5.010;
use strict;
use warnings;
my @x = (1, 2, 3);
my @y = qw(1 2 3);
say "[@x] and [@y] match" if @x ~~ @y;
Run Code Online (Sandbox Code Playgroud)
在内部,比较器通过使用join将两个数组转换为字符串并使用比较字符串来比较两个数组
eq
.
我想这是一个有效的方法,但只要我们使用字符串比较,我宁愿使用类似的东西:
#!/usr/bin/perl
use strict;
use warnings;
use List::AllUtils qw( each_arrayref );
my @x = qw(1 2 3);
my @y = (1, 2, 3);
print "[@x] and [@y] match\n" if elementwise_eq( \(@x, @y) );
sub elementwise_eq {
my ($xref, $yref) = @_;
return unless @$xref == @$yref;
my $it = each_arrayref($xref, $yref);
while ( my ($x, $y) = $it->() ) {
return unless $x eq $y;
}
return 1;
}
Run Code Online (Sandbox Code Playgroud)
如果您要比较的数组很大,那么加入它们将会做很多工作并消耗大量内存,而不是逐个比较每个元素.
更新:当然,应该测试这样的陈述.简单的基准:
#!/usr/bin/perl
use strict;
use warnings;
use Array::Compare;
use Benchmark qw( cmpthese );
use List::AllUtils qw( each_arrayref );
my @x = 1 .. 1_000;
my @y = map { "$_" } 1 .. 1_000;
my $comp = Array::Compare->new;
cmpthese -5, {
iterator => sub { my $r = elementwise_eq(\(@x, @y)) },
array_comp => sub { my $r = $comp->compare(\(@x, @y)) },
};
Run Code Online (Sandbox Code Playgroud)
这是最糟糕的情况,elementwise_eq
必须遍历两个数组中的每个元素1_000次,并显示:
Rate iterator array_comp iterator 246/s -- -75% array_comp 1002/s 308% --
另一方面,最好的情况是:
my @x = map { rand } 1 .. 1_000;
my @y = map { rand } 1 .. 1_000;
Run Code Online (Sandbox Code Playgroud)
Rate array_comp iterator array_comp 919/s -- -98% iterator 52600/s 5622% --
iterator
然而,性能下降很快:
my @x = 1 .. 20, map { rand } 1 .. 1_000;
my @y = 1 .. 20, map { rand } 1 .. 1_000;
Run Code Online (Sandbox Code Playgroud)
Rate iterator array_comp iterator 10014/s -- -23% array_comp 13071/s 31% --
我没有看内存利用率.
Eth*_*her 22
还有Test :: More的is_deeply()函数,它也会精确显示结构的不同之处,或者Test :: Deep的eq_deeply(),它不需要测试工具(只返回true或false).
cha*_*aos 14
不是内置的,但有Array :: Compare.
这是Perl核心遗漏的操作之一,因为我认为这是教学的原因 - 也就是说,如果你试图这样做,可能会出现问题.我认为,最具说明性的例子是没有核心read_entire_file
功能; 基本上,在核心中提供该功能会让人们认为这样做是个好主意,但是,Perl的设计方式可以轻轻地推动您逐行处理文件,这通常会更多有效率和其他更好的想法,但新手程序员很少习惯它,他们需要一些鼓励去实现.
这同样适用于:通过比较两个数组,可能有更好的方法来确定你想要完成的决定.不是必然,但可能.所以Perl正在推动你思考实现目标的其他方法.
Perl 5.10为您提供智能匹配运算符.
use 5.010;
if( @array1 ~~ @array2 )
{
say "The arrays are the same";
}
Run Code Online (Sandbox Code Playgroud)
否则,正如你所说,你将有自己的顶级.
只要您使用perl 5.10或更高版本,就可以使用智能匹配运算符.
if (@array1 ~~ @array2) {...}
Run Code Online (Sandbox Code Playgroud)
更简单的解决方案更快:
#!/usr/bin/perl
use strict;
use warnings;
use Array::Compare;
use Benchmark qw( cmpthese );
use List::AllUtils qw( each_arrayref );
my @x = 1 .. 1_000;
my @y = map { "$_" } 1 .. 1_000;
my $comp = Array::Compare->new;
cmpthese -2, {
iterator => sub { my $r = elementwise_eq(\(@x, @y)) },
my_comp => sub { my $r = my_comp(\(@x, @y)) },
array_comp => sub { my $r = $comp->compare(\(@x, @y)) },
};
@x = 1 .. 20, map { rand } 1 .. 1_000;
@y = 1 .. 20, map { rand } 1 .. 1_000;
cmpthese -2, {
iterator => sub { my $r = elementwise_eq(\(@x, @y)) },
my_comp => sub { my $r = my_comp(\(@x, @y)) },
array_comp => sub { my $r = $comp->compare(\(@x, @y)) },
};
sub elementwise_eq {
my ($xref, $yref) = @_;
return unless @$xref == @$yref;
my $it = each_arrayref($xref, $yref);
while ( my ($x, $y) = $it->() ) {
return unless $x eq $y;
}
return 1;
}
sub my_comp {
my ($xref, $yref) = @_;
return unless @$xref == @$yref;
my $i;
for my $e (@$xref) {
return unless $e eq $yref->[$i++];
}
return 1;
}
Run Code Online (Sandbox Code Playgroud)
并导致perl 5, version 14, subversion 2 (v5.14.2) built for x86_64-linux-gnu-thread-multi
:
Rate iterator array_comp my_comp
iterator 1544/s -- -67% -80%
array_comp 4697/s 204% -- -41%
my_comp 7914/s 413% 68% --
Rate iterator array_comp my_comp
iterator 63846/s -- -1% -75%
array_comp 64246/s 1% -- -75%
my_comp 252629/s 296% 293% --
Run Code Online (Sandbox Code Playgroud)