Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 如何在perl中分解数组散列中的公共元素?_Arrays_Perl_Hash_Intersection - Fatal编程技术网

Arrays 如何在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

我试图在Perl中的数组散列中查找元素的任何交点

比如说

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有一个?它应该尽可能多地组合在一起?