比方說,我有這些陣列如何比較2個數組並分成3組?
my @new = qw/a b c d e/;
my @old = qw/a b d e f/;
,我想他們相比,所以我得到含有不同
- 與處於
@new
而不是元素的數組3個新的陣列@old
:C - 與不是在
@new
的元素和在@old
陣列:F - 與AR元素的數組E在兩個
@new
和@old
:A B dé
我思考exists
功能,但只適用於哈希我想。
更新:我搞砸了字母的例子。
比方說,我有這些陣列如何比較2個數組並分成3組?
my @new = qw/a b c d e/;
my @old = qw/a b d e f/;
,我想他們相比,所以我得到含有不同
@new
而不是元素的數組3個新的陣列@old
:C@new
的元素和在@old
陣列:F@new
和@old
:A B dé我思考exists
功能,但只適用於哈希我想。
更新:我搞砸了字母的例子。
這是我多次使用過的函數。
sub compute_sets {
my ($ra, $rb) = @_;
my (@a, @b, @ab, %a, %b, %seen);
@a{@$ra} =();
@b{@$rb} =();
foreach (keys %a, keys %b) {
next if $seen{$_}++;
if (exists $a{$_} && exists $b{$_}) {
push(@ab, $_);
}
elsif (exists $a{$_}) {
push(@a, $_);
}
else {
push(@b, $_);
}
}
return(\@a, \@b, \@ab);
}
它返回到包含在所述第一/第二/兩個列表的元素數組的引用:
my @new = qw/a b c d e/;
my @old = qw/a b d e f/;
my ($new_only, $old_only, $both) = compute_sets(\@new, \@old);
say 'new only: ', join ' ', @$new_only; # c
say 'old only: ', join ' ', @$old_only; # f
say 'both: ', join ' ', @$both; # e a b d
更新2:正如Michael Carman指出的,如果元素重複,我的算法將失敗。因此,一個固定的解決方案使用一個更哈希:
my (%count, %old);
$count{$_} = 1 for @new;
$old{$_}++ or $count{$_}-- for @old;
# %count is now really like diff(1)
my (@minus, @plus, @intersection);
foreach (keys %count) {
push @minus, $_ if $count{$_} < 0;
push @plus, $_ if $count{$_} > 0;
push @intersection, $_ if $count{$_} == 0;
};
更新:貌似這個解決方案還包括什麼是在常見問題解答:
push @difference, $_ if $count{$_};
push @union, $_;
除了他希望交叉點*不是聯合。 – Axeman 2011-03-24 16:38:52
@Axeman:是的。 '@ common'是路口。 – Dallaylaen 2011-03-24 17:57:09
表示同意,但常見問題有'@ union'。我提高了您的解決方案 - 我認爲這是一個很好的解決方案,但評論說FAQ不會以相同的方式覆蓋*。 – Axeman 2011-03-24 18:49:27
如何:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my @new = qw/a b c d e/;
my @old = qw/a b d e f/;
my %new = map{$_ => 1} @new;
my %old = map{$_ => 1} @old;
my (@new_not_old, @old_not_new, @new_and_old);
foreach my $key(@new) {
if (exists $old{$key}) {
push @new_and_old, $key;
} else {
push @new_not_old, $key;
}
}
foreach my $key(@old) {
if (!exists $new{$key}) {
push @old_not_new, $key;
}
}
print Dumper\@new_and_old;
print Dumper\@new_not_old;
print Dumper\@old_not_new;
輸出:
$VAR1 = [
'a',
'b',
'd',
'e'
];
$VAR1 = [
'c'
];
$VAR1 = [
'f'
];
另請參見Algorithm::Diff
一覽::比較處理這種類型的問題。
#!/usr/bin/perl
use strict;
use warnings;
use List::Compare;
my @new = qw/a b c d e/;
my @old = qw/a b d e f/;
my $lc = List::Compare->new(\@new, \@old);
# an array with the elements that are in @new and not in @old : c
my @Lonly = $lc->get_Lonly;
print "\@Lonly: @Lonly\n";
# an array with the elements that are not in @new and in @old : f
my @Ronly = $lc->get_Ronly;
print "\@Ronly: @Ronly\n";
# an array with the elements that are in both @new and @old : a b d e
my @intersection = $lc->get_intersection;
print "\@intersection: @intersection\n";
__END__
** prints
@Lonly: c
@Ronly: f
@intersection: a b d e
這並沒有給出所需的分組。用我得到的。十字路口:a b d e。差異:c f。 union:a b c d e f。 – 2011-03-24 15:39:09
該答案的主要思想是「使用散列」 – 2011-03-24 16:04:51