在 Perl 中,是否有一种内置方法来比较两个数组是否相等? [英] In Perl, is there a built in way to compare two arrays for equality?
问题描述
我有两个字符串数组,我想比较它们是否相等:
我的@array1 = ("part1", "part2", "part3", "part4");我的@array2 = ("part1", "PART2", "part3", "part4");
有没有像标量那样比较数组的内置方法?我试过了:
if (@array1 == @array2) {...}
但它只是在标量上下文中评估每个数组,因此比较每个数组的长度.
我可以滚动自己的函数来执行此操作,但它似乎是一个低级操作,应该有一个内置的方法来执行它.有吗?
遗憾的是,我无法访问 5.10+ 或可选组件.
有新的智能匹配运算符:
#!/usr/bin/perl使用 5.010;使用严格;使用警告;我的@x = (1, 2, 3);我的@y = qw(1 2 3);如果@x ~~ @y 则说[@x] 和 [@y] 匹配";
关于 Array::Compare:
<块引用>比较器在内部比较两个数组,方法是使用 join 将两个数组转换为字符串并使用 eq
比较字符串.
我想这是一个有效的方法,但只要我们使用字符串比较,我宁愿使用类似的东西:
#!/usr/bin/perl使用严格;使用警告;使用 List::AllUtils qw( each_arrayref );我的@x = qw(1 2 3);我的@y = (1, 2, 3);print "[@x] and [@y] match
" if elementwise_eq( (@x, @y) );子 elementwise_eq {我的 ($xref, $yref) = @_;返回除非@$xref == @$yref;我的 $it = each_arrayref($xref, $yref);而 ( 我的 ($x, $y) = $it->() ) {返回除非 $x eq $y;}返回 1;}
如果您要比较的数组很大,加入它们会做大量工作并消耗大量内存,而不仅仅是逐个比较每个元素.
更新:当然,应该测试这些语句.简单的基准测试:
#!/usr/bin/perl使用严格;使用警告;使用数组::比较;使用基准 qw( cmpthese );使用 List::AllUtils qw( each_arrayref );我的@x = 1 .. 1_000;我的 @y = 地图 { "$_" } 1 .. 1_000;我的 $comp = Array::Compare->new;cmpthese -5, {迭代器=>子 { 我的 $r = elementwise_eq((@x, @y)) },array_comp =>子 { 我的 $r = $comp->比较((@x, @y)) },};
这是最坏的情况,其中 elementwise_eq
必须遍历两个数组中的每个元素 1_000 次,它显示:
另一方面,最好的情况是:
我的@x = map { rand } 1 .. 1_000;我的 @y = 地图 { 兰德 } 1 .. 1_000;
<上一页>速率 array_comp 迭代器array_comp 919/s -- -98%迭代器 52600/s 5622% --
iterator
性能下降很快,但是:
我的@x = 1 .. 20, map { rand } 1 .. 1_000;我的@y = 1 .. 20,地图 { rand } 1 .. 1_000;
<上一页>速率迭代器 array_comp迭代器 10014/s -- -23%array_comp 13071/s 31% --
我没有查看内存利用率.
I have two arrays of strings that I would like to compare for equality:
my @array1 = ("part1", "part2", "part3", "part4");
my @array2 = ("part1", "PART2", "part3", "part4");
Is there a built-in way to compare arrays like there is for scalars? I tried:
if (@array1 == @array2) {...}
but it just evaluated each array in scalar context, and so compared the length of each array.
I can roll my own function to do it, but it seems like such a low-level operation that there should be a built-in way to do it. Is there?
Edit: sadly, I don't have access to 5.10+ or optional components.
There is the new smart match operator:
#!/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;
Regarding Array::Compare:
Internally the comparator compares the two arrays by using join to turn both arrays into strings and comparing the strings using
eq
.
I guess that is a valid method, but so long as we are using string comparisons, I would much rather use something like:
#!/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
" 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;
}
If the arrays you are comparing are large, joining them is going to do a lot of work and consume a lot of memory than just comparing each element one by one.
Update: Of course, one should test such statements. Simple benchmarks:
#!/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)) },
};
This is the worst case scenario where elementwise_eq
has to go through each and every element in both arrays 1_000 times and it shows:
Rate iterator array_comp iterator 246/s -- -75% array_comp 1002/s 308% --
On the other hand, the best case scenario is:
my @x = map { rand } 1 .. 1_000;
my @y = map { rand } 1 .. 1_000;
Rate array_comp iterator array_comp 919/s -- -98% iterator 52600/s 5622% --
iterator
performance drops quite quickly, however:
my @x = 1 .. 20, map { rand } 1 .. 1_000;
my @y = 1 .. 20, map { rand } 1 .. 1_000;
Rate iterator array_comp iterator 10014/s -- -23% array_comp 13071/s 31% --
I did not look at memory utilization.
这篇关于在 Perl 中,是否有一种内置方法来比较两个数组是否相等?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!