我有两个数组,@a
和 @b
。我想比较这两个数组中的元素。
my @a = qw"abc def efg ghy klm ghn";
my @b = qw"def ghy jgk lom com klm";
如果任何元素匹配,则设置一个标记。有没有简单的方法来做到这一点?
首先,你的两个数组需要正确书写。
@a = ("abc","def","efg","ghy","klm","ghn");
@b = ("def","efg","ghy","klm","ghn","klm");
其次,针对任意数组(例如其元素可能是对其他数据结构的引用),您可以使用Data::Compare
。
对于其元素为标量的数组,您可以使用List::MoreUtils
的pairwise BLOCK ARRAY1 ARRAY2
进行比较,其中BLOCK是您的比较子例程。如果没有List::MoreUtils,则您可以通过以下方式模拟pairwise
:
if (@a != @b) {
$equals = 0;
} else {
$equals = 1;
foreach (my $i = 0; $i < @a; $i++) {
# Ideally, check for undef/value comparison here as well
if ($a[$i] != $b[$i]) { # use "ne" if elements are strings, not numbers
# Or you can use generic sub comparing 2 values
$equals = 0;
last;
}
}
}
顺便说一句,我不确定但List::Compare可能总是对列表进行排序。我不确定它是否可以进行成对比较。
@a = qw"abc def efg ghy klm ghn"
不行呢?它不应该只是在用户自定义的分隔符 ('"
' 在这种情况下) 内被解析为列表吗?它应该与 qw//
或 qw||
或 qw()
完全相同。 - Oesor创建一个交集函数,它将返回存在于两个列表中的项目列表。然后,您的返回值取决于交集列表中的项目数量。
您可以在网络上轻松找到Perl的最佳intersect实现。我记得几年前就在寻找它。
以下是我找到的代码:
my @array1 = (1, 2, 3); my @array2 = (2, 3, 4); my %original = (); my @isect = ();
map { $original{$_} = 1 } @array1; @isect = grep { $original{$_} } @array2;
对于“如果任何元素匹配”的要求,使用集合的交集:
sub set{
my %set = map { $_, undef }, @_;
return sort keys %set;
}
sub compare{
my ($listA,$listB) = @_;
return ( (set(@$listA)-set(@$listB)) > 0)
}
use warnings;
use strict;
my @a = split /,/, "abc,def,efg,ghy,klm,ghn";
my @b = split /,/, "def,ghy,jgk,lom,com,klm";
my $flag = 0;
my %a;
@a{@a} = (1) x @a;
for (@b) {
if ($a{$_}) {
$flag = 1;
last;
}
}
print "$flag\n";
%a
的键填充为@a
的元素,而值全部为1。这利用了Perl允许使用相同名称的不同变量类型,哈希切片和标量上下文中的数组。但是,此代码无法用于比较具有非唯一值的数组。 - beasymy @a = qw' abc def efg ghy klm ghn ';
my @b = qw' def ghy jgk lom com klm ';
my $flag;
foreach my $item(@a) {
$flag = @b~~$item ? 0 : 1;
last if !$flag;
}
~~
)。$item ~~ @b
吗?即使如此,如果数组具有相同的元素但顺序不同,它是否会返回true?如果不是,请解释一下代码! - U. Windl如果您认为不同顺序的数组是不同的,您可以使用Array::Diff。
if (Array::Diff->diff(\@a, \@b)->count) {
# not_same
} else {
# same
}
这是Perl语言。'显而易见'的解决方案:
my @a = qw"abc def efg ghy klm ghn";
my @b = qw"def ghy jgk lom com klm";
print "arrays equal\n"
if @a == @b and join("\0", @a) eq join("\0", @b);
给定@a中不存在"\0"。
但感谢确认除了自己编写之外没有其他通用解决方案。
@a == @b
只是一种性能优化,如果数组中有许多或大量元素,它是否会非常低效呢?例如,如果元素是引用,它能否正常工作? - U. Windlmy @a1 = qw|a b c d|;
my @a2 = qw|b c d e|;
for my $i (0..$#a1) {
say "element $i of array 1 was not found in array 2"
unless grep {$_ eq $a1[$i]} @a2
}
对于小的 n
,暴力破解应该可以解决问题:
my $flag = 0;
foreach my $i (@a) {
foreach my $k (@b) {
if ($i eq $k) {
$flag = 1;
last;
}
}
}
对于大的n
,使用哈希表:
my $flag = 0;
my %aa = ();
$aa{$_} = 1 foreach (@a);
foreach my $i (@b) {
if ($aa{$i}) {
$flag = 1;
last;
}
}
当一个很大的n
是|@a| + |@b| > ~1000
项时
|@a| + |@b| == 1000
,它可能意味着 |@a| == 2 && |@b| == 998
或者 |@a| == 500 && |@b| == 500
。然而,在前一种情况下,比较的次数将是1996,而在后一种情况下,比较的次数将是250000。因此,基本上重要的不是总和,而是乘积。 - U. Windl
$a[$i] eq $b[$i]
;(2) 搜索任何匹配项的答案,例如$a[$i] eq $b[$j]
。那么您的目标是什么? - FMc0
,如果没有则返回1
。 - Sinan Ünür