Arrays 如何在perl中分解数组散列中的公共元素?
我试图在Perl中的数组散列中查找元素的任何交点 比如说Arrays 如何在perl中分解数组散列中的公共元素?,arrays,perl,hash,intersection,Arrays,Perl,Hash,Intersection,我试图在Perl中的数组散列中查找元素的任何交点 比如说 my %test = ( Lot1 => [ "A","B","C"], Lot2 => [ "A","B","C"], Lot3 => ["C"], Lot4 => ["E","F"], ); 我想要的结果是 Lot1和Lot2具有AB Lot
my %test = (
Lot1 => [ "A","B","C"],
Lot2 => [ "A","B","C"],
Lot3 => ["C"],
Lot4 => ["E","F"],
);
我想要的结果是
- Lot1和Lot2具有AB
- Lot1、Lot2和Lot3具有C
- Lot4有E和F
谢谢。数组::Utils有一个交集操作,您可以在其中测试两个数组的交集。但这只是你想做的事情的起点 因此,我认为您需要首先反转查找:
my %member_of;
foreach my $key ( keys %test ) {
foreach my $element ( @{$test{$key}} ) {
push ( @{$member_of{$element}}, $key );
}
}
print Dumper \%member_of;
给予:
$VAR1 = {
'A' => [
'Lot1',
'Lot2'
],
'F' => [
'Lot4'
],
'B' => [
'Lot1',
'Lot2'
],
'E' => [
'Lot4'
],
'C' => [
'Lot1',
'Lot2',
'Lot3'
]
};
$VAR1 = {
'Lot1,Lot2,Lot3' => [
'C'
],
'Lot1,Lot2' => [
'A',
'B'
],
'Lot4' => [
'E',
'F'
]
};
然后将其折叠为一个关键点集:
my %new_set;
foreach my $element ( keys %member_of ) {
my $set = join( ",", @{ $member_of{$element} } );
push( @{ $new_set{$set} }, $element );
}
print Dumper \%new_set;
给予:
$VAR1 = {
'A' => [
'Lot1',
'Lot2'
],
'F' => [
'Lot4'
],
'B' => [
'Lot1',
'Lot2'
],
'E' => [
'Lot4'
],
'C' => [
'Lot1',
'Lot2',
'Lot3'
]
};
$VAR1 = {
'Lot1,Lot2,Lot3' => [
'C'
],
'Lot1,Lot2' => [
'A',
'B'
],
'Lot4' => [
'E',
'F'
]
};
因此,总体而言:
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
my %test = (
Lot1 => [ "A", "B", "C" ],
Lot2 => [ "A", "B", "C" ],
Lot3 => ["C"],
Lot4 => [ "E", "F" ],
);
my %member_of;
foreach my $key ( sort keys %test ) {
foreach my $element ( @{ $test{$key} } ) {
push( @{ $member_of{$element} }, $key );
}
}
my %new_set;
foreach my $element ( sort keys %member_of ) {
my $set = join( ",", @{ $member_of{$element} } );
push( @{ $new_set{$set} }, $element );
}
foreach my $set ( sort keys %new_set ) {
print "$set contains: ", join( ",", @{ $new_set{$set} } ), "\n";
}
我不认为有更有效的方法来解决这个问题,因为您正在将每个数组相互比较,并从中形成一个新的复合键
这将为您提供:
Lot1,Lot2 contains: A,B
Lot1,Lot2,Lot3 contains: C
Lot4 contains: E,F
这可以通过两个简单的哈希转换来完成:
- 构建一个哈希表,列出每个项目所在的所有批次
- 将其转换为列出每个批次组合的所有项目的哈希
use strict;
use warnings 'all';
use feature 'say';
my %test = (
Lot1 => [ "A", "B", "C" ],
Lot2 => [ "A", "B", "C" ],
Lot3 => ["C"],
Lot4 => [ "E", "F" ],
);
my %items;
for my $lot ( keys %test ) {
for my $item ( @{ $test{$lot} } ) {
push @{ $items{$item} }, $lot;
}
}
my %lots;
for my $item ( keys %items ) {
my $lots = join '!', sort @{ $items{$item} };
push @{ $lots{$lots} }, $item;
}
for my $lots ( sort keys %lots ) {
my @lots = split /!/, $lots;
my $items = join '', @{ $lots{$lots} };
$lots = join ', ', @lots;
$lots =~ s/.*\K,/ and/;
printf "%s %s %s\n", $lots, @lots > 1 ? 'have' : 'has', $items;
}
输出
它生成一个如下所示的%items
散列
{
A => ["Lot2", "Lot1"],
B => ["Lot2", "Lot1"],
C => ["Lot2", "Lot3", "Lot1"],
E => ["Lot4"],
F => ["Lot4"],
}
{
"Lot1!Lot2" => ["A", "B"],
"Lot1!Lot2!Lot3" => ["C"],
"Lot4" => ["E", "F"],
}
从中可以看到一个%lots
散列,如下所示
{
A => ["Lot2", "Lot1"],
B => ["Lot2", "Lot1"],
C => ["Lot2", "Lot3", "Lot1"],
E => ["Lot4"],
F => ["Lot4"],
}
{
"Lot1!Lot2" => ["A", "B"],
"Lot1!Lot2!Lot3" => ["C"],
"Lot4" => ["E", "F"],
}
您链接到特定版本的List::Compare有什么原因吗?如果不是,您可以使用。不,没有理由链接到该版本,但它似乎也是您链接的同一版本?”James E Keenan>List-Compare-0.53'是的,如果你选择最新的。我的意思是“更喜欢Metapan而不是search.cpan.org,因为它总是有最新的版本,而且对用户更友好”;)好的,更新了链接。Lot1和Lot2有一个?它应该尽可能多地组合在一起?