我有两个数组:
@array1 = (A,B,C,D,E,F);
@array2 = (A,C,H,D,E,G);
阵列的大小可能不同。我想知道数组之间有多少不匹配。索引应该是相同的。在这种情况下,有三种不匹配:b->c
,c->h
和F->G
。(C
中的“$array[2]
”不应视为与C
中的“$array[1]
”我想知道不匹配的数量以及不匹配。
foreach my $a1 ( 0 .. $#array1) {
foreach my $a2( 0 .. $#array2)
if($array1[$a1] ne $array2[$a2]) {
}
}
}
my %array_one = map {$_, 1} @array1;
my @difference = grep {!$array_one {$_}} @array1;
print "@difference\n";
答:给我H
,G
但不是C
。
凭借我的小Perl知识,我尝试了这一点,没有结果。你能建议我怎么处理这件事吗?您的建议和指示将非常有用。
答案 0 :(得分:4)
你不应该有嵌套循环。您只需要浏览一次索引。
use List::Util qw( max );
my @mismatches;
for my $i (0..max($#array1, $#array2)) {
push @mismatches, $i
if $i >= @array1
|| $i >= @array2
|| $array1[$i] ne $array2[$i];
}
}
say "There are " . (0+@mismatches) . " mismatches";
for my $i (@mismatches) {
...
}
由于您提到grep
,因此您可以将for
替换为grep
:
use List::Util qw( max );
my @mismatches =
grep { $_ >= @array1
|| $_ >= @array2
|| array1[$_] ne $array2[$_] }
0 .. max($#array1, $#array2);
say "There are " . (0+@mismatches) . " mismatches";
for my $i (@mismatches) {
...
}
答案 1 :(得分:1)
当您不希望这样做时,您正在迭代两个数组。
@array1 = ("A","B","C","D","E","F");
@array2 = ("A","C","H","D","E","G");
foreach my $index (0 .. $#array1) {
if ($array1[$index] ne $array2[$index]) {
print "Arrays differ at index $index: $array1[$index] and $array2[$index]\n";
}
}
输出:
Arrays differ at index 1: B and C
Arrays differ at index 2: C and H
Arrays differ at index 5: F and G
答案 2 :(得分:1)
以下代码构建了不匹配对的列表,然后将其打印出来。
@a1 = (A,B,C,D,E,F);
@a2 = (A,C,H,D,E,G);
@diff = map { [$a1[$_] => $a2[$_]] }
grep { $a1[$_] ne $a2[$_] }
(0..($#a1 < $#a2 ? $#a1 : $#a2));
print "$_->[0]->$_->[1]\n" for @diff
答案 3 :(得分:1)
那么,首先,您将要查看其中一个数组的每个元素,并将其与另一个数组的相同元素进行比较。 List :: MoreUtils提供了一种简单的方法:
use v5.14;
use List::MoreUtils qw(each_array);
my @a = qw(a b c d);
my @b = qw(1 2 3);
my $ea = each_array @a, @b;
while ( my ($a, $b) = $ea->() ) {
say "a = $a, b = $b, idx = ", $ea->('index');
}
您可以通过检查while循环内部来扩展它以查找不匹配的位置(注意:这假设您的数组最后没有undefs,或者如果它们这样做,则undef与拥有一个较短的数组):
my @mismatch;
my $ea = each_array @a, @b;
while ( my ($a, $b) = $ea->() ) {
if (defined $a != defined $b || $a ne $b) {
push @mismatch, $ea->('index');
}
}
然后:
say "Mismatched count = ", scalar(@mismatch), " items are: ", join(q{, }, @mismatch);
答案 4 :(得分:1)
以下是使用each_arrayref
中的List::MoreUtils的示例。
sub diff_array{
use List::MoreUtils qw'each_arrayref';
return unless @_ && defined wantarray;
my @out;
my $iter = each_arrayref(@_);
my $index = 0;
while( my @current = $iter->() ){
next if all_same(@current);
unshift @current, $index;
push @out, \@current;
}continue{ ++$index }
return @out;
}
如果您打算使用它来经常确定差异的数量,那么此版本应该更快。输出完全相同。返回一个数字时,它不需要那么努力
了解更多信息,请阅读wantarray
。
sub diff_array{
use List::MoreUtils qw'each_arrayref';
return unless @_ && defined wantarray;
my $iter = each_arrayref(@_);
if( wantarray ){
# return structure
my @out;
my $index = 0;
while( my @current = $iter->() ){
next if all_same(@current);
unshift @current, $index;
push @out, \@current;
}continue{ ++$index }
return @out;
}else{
# only return a count of differences
my $out = 0;
while( my @current = $iter->() ){
++$out unless all_same @current;
}
return $out;
}
}
diff_array
使用子例程all_same
来确定所有当前元素列表是否相同。
sub all_same{
my $head = shift;
return undef unless @_; # not enough arguments
for( @_ ){
return 0 if $_ ne $head; # at least one mismatch
}
return 1; # all are the same
}
获得差异的数量:
print scalar diff_array \@array1, \@array2;
my $count = diff_array \@array1, \@array2;
获取差异列表:
my @list = diff_array \@array1, \@array2;
同时获得两者:
my $count = my @list = diff_array \@array1, \@array2;
您提供的输入的输出:
(
[ 1, 'B', 'C' ],
[ 2, 'C', 'H' ],
[ 5, 'F', 'G' ]
)
使用示例
my @a1 = qw'A B C D E F';
my @a2 = qw'A C H D E G';
my $count = my @list = diff_array \@a1, \@a2;
print "There were $count differences\n\n";
for my $group (@list){
my $index = shift @$group;
print " At index $index\n";
print " $_\n" for @$group;
print "\n";
}
答案 5 :(得分:0)
你有正确的想法,但你只需要一个循环,因为你正在查看每个索引并比较数组之间的条目:
foreach my $a1 ( 0 .. $#array1) {
if($array1[$a1] ne $array2[$a1]) {
print "$a1: $array1[$a1] <-> $array2[$a1]\n";
}
}