我有两个数组,@a
和@b
。我想对两个数组的元素进行比较。
my @a = qw"abc def efg ghy klm ghn";
my @b = qw"def ghy jgk lom com klm";
如果任何元素匹配,则设置一个标志。有没有简单的方法呢?
答案 0 :(得分:9)
首先,需要正确编写2个数组。
@a = ("abc","def","efg","ghy","klm","ghn");
@b = ("def","efg","ghy","klm","ghn","klm");
其次,对于任意数组(例如,其元素可能引用其他数据结构的数组),您可以使用Data::Compare
。
对于元素为标量的数组,可以使用List::MoreUtils
pairwise BLOCK ARRAY1 ARRAY2
进行比较,其中BLOCK是您的比较子例程。您可以通过以下方式模拟pairwise
(如果您没有List :: MoreUtils访问权限):
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;
}
}
}
P.S。我不确定,但List::Compare可能总是对列表进行排序。我不确定它是否可以进行成对比较。
答案 1 :(得分:7)
if ( scalar List::Compare->new(\@a, \@b)->get_intersection ) {
…
}
答案 2 :(得分:4)
选中以创建交叉函数,该函数将返回两个列表中存在的项目列表。然后,您的返回值取决于相交列表中的项目数。
您可以在网上轻松找到有关Perl的最佳实现。我记得几年前找它。
这是我发现的:
my @array1 = (1, 2, 3); my @array2 = (2, 3, 4); my %original = (); my @isect = (); map { $original{$_} = 1 } @array1; @isect = grep { $original{$_} } @array2;
答案 3 :(得分:2)
这是一种方式:
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";
答案 4 :(得分:1)
my @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;
}
请注意,您需要使用Perl 5.10或更高版本才能使用smart match operator(~~
)。
答案 5 :(得分:1)
根据'if 任何元素匹配'的要求,使用集合的交集:
sub set{
my %set = map { $_, undef }, @_;
return sort keys %set;
}
sub compare{
my ($listA,$listB) = @_;
return ( (set(@$listA)-set(@$listB)) > 0)
}
答案 6 :(得分:0)
蛮力应该为小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
个项目
答案 7 :(得分:0)
恕我直言,你应该使用List::MoreUtils::pairwise。但是,如果由于某种原因你不能,那么下面的sub将为每个索引返回1,其中第一个数组中的值比较等于第二个数组中的值。您可以根据需要概括此方法,并根据需要传递自己的比较器,但此时,只需安装List::MoreUtils就可以更有效地利用您的时间。
use strict; use warnings;
my @a = qw(abc def ghi jkl);
my @b = qw(abc dgh dlkfj jkl kjj lkm);
my $map = which_ones_equal(\@a, \@b);
print join(', ', @$map), "\n";
sub which_ones_equal {
my ($x, $y, $compare) = @_;
my $last = $#$x > $#$y ? $#$x : $#$y;
no warnings 'uninitialized';
return [ map { 0 + ($x->[$_] eq $y->[$_]) } $[ .. $last ];
}
答案 8 :(得分:0)
这是Perl。显而易见的&#39;溶液:
<?php
$sql2 = "SELECT * FROM smf_log_digest WHERE note_type = 'topic'";
$result2 = $conn->query($sql2);
if ($result2->num_rows > 0) {
while($row2 = $result2->fetch_assoc()) {
$number = $row2["id_msg"];
$sql3 = "SELECT * FROM smf_messages WHERE id_msg = $number LIMIT 10";
$result3 = $conn->query($sql3);
if ($result3->num_rows > 0) {
while($row3 = $result3->fetch_assoc()) {
echo $row3["subject"];
}
} else {
echo "";
}
}
} else {
echo "";
}
$conn->close();
?>
给出&#34; \ 0&#34;不在@a。
但是,感谢您确认没有其他通用解决方案,而不是滚动自己的解决方案。
答案 9 :(得分:0)
my @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
}
答案 10 :(得分:0)
如果您认为具有不同顺序的数组是不同的,则可以使用Array::Diff
if (Array::Diff->diff(\@a, \@b)->count) {
# not_same
} else {
# same
}
答案 11 :(得分:0)
这个问题可能还意味着两件事,即“如果有任何元素匹配,则设置一个标志”:
对于情况1,您可以这样做:
# iterate over all positions, and compare values at that position
my @matches = grep { $a[$_] eq $b[$_] } 0 .. $#a;
# set flag if there's any match at the same position
my $flag = 1 if @matches;
对于情况2,您可以这样做:
# make a hash of @a and check if any @b are in there
my %a = map { $_ => 1 } @a;
my @matches = grep { $a{$_} } @b;
# set flag if there's matches at any position
my $flag = 1 if @matches;
请注意,在第一种情况下,@matches保留存在匹配元素的索引,在第二种情况下,@ matches保留匹配值在它们出现在@b中的顺序。