Perl将数组的散列与另一个数组

时间:2016-04-14 19:46:20

标签: arrays perl hash hashmap compare

我试图将所有数组值(完整数组)与哈希值(即数组)进行比较,如果找到匹配项,则将哈希键推送到新数组。 下面的代码比较哈希值是不是数组但是如何比较它的数组?

%hash=(
       storeA=>['milk','eggs'],
       storeB=>['milk','fruits','eggs','vegetables'],
       storeC=>['milk','fruits','eggs'],
      );

@array = (
        'fruits',
        'milk',
        'eggs'
    );

要比较的代码

use strict;
use warnings;
use Data::Dumper;

foreach my $thing (@array)   {
     foreach ((my $key, my $value) = each %hash)   { 
                 if ($value eq $thing)   {
                       push @new_array, $key;
                }
          }
   }
  print Dumper(\@new_array);

预期输出

@new_array = (
               storeB,
               storeC
       );

5 个答案:

答案 0 :(得分:2)

您还可以使用allany形式List::Util的组合:

while ((my $key, my $value) = each %hash) {
    if ( all { my $temp = $_; any { $_ eq $temp } @$value } @array ) {  
        push @new_array, $key;
    }
}

所以在这里你要找的是散列中给定数组中存在@array的所有元素的情况。

答案 1 :(得分:1)

找到两个集合的交集,如果其元素的数量是数组中元素的数量,则要存储密钥:

#!/usr/bin/perl
use warnings;
use strict;


sub intersect {
    my ($arr1, $arr2) = @_;
    my %intersection;
    $intersection{$_}{0}++ for @$arr1;
    $intersection{$_}{1}++ for @$arr2;
    return grep 2 == keys %{ $intersection{$_} }, keys %intersection
}


my %hash = (
            storeA => [qw[ milk eggs ]],
            storeB => [qw[ milk fruits eggs vegetables ]],
            storeC => [qw[ milk fruits eggs ]],
           );

my @array = qw( fruits milk eggs );

my @new_array;

while (my ($store, $arr) = each %hash) {  # while, not for!
    push @new_array, $store if @array == intersect(\@array, $arr);
}

use Data::Dumper;
print Dumper(\@new_array);

答案 2 :(得分:1)

试试吧。我在这里做的一个小技巧。 grep用于从数组中过滤元素。

我创建了变量$joined_array,其中包含|个分隔的@array数据。然后我将变量传递给grep。

诀窍是,当数组与标量数据进行比较时,比较就是行为,即带有标量数据的数组元素的总数。

my @array = qw(one two three);

if(@array == 3)
{
    print "Hi\n";

}

此处条件在内部以3 == 3运行。

我在这里做了同样的逻辑。

use warnings;
use strict;
my %hash=(
    "storeA"=>['milk','eggs'],
    "storeB"=>['milk','fruits','eggs','vegetables'],
    "storeC"=>['milk','fruits','eggs'],
);

my @array = (
    'fruits',
    'milk',
    'eggs'
);

my @new_array;

my $joined_array = join("|",@array);

foreach (keys  %hash)
{

 push(@new_array,$_) if  ((grep{ /\b$joined_array\b/ } @{$hash{$_}}) >= scalar @array);

}

print "$_\n" for @new_array

答案 3 :(得分:1)

我会在每个商店的库存数组中构建一个哈希值。这是一种浪费的方法,但只要真实的数据不是很大,就不会那么严重

喜欢这个。内部grep语句计算此商店中可用的@list中的项目数,并将其与列表中的项目数进行比较,如果所有内容都在,则返回 true 股票

如果这是一个真实的情况(我怀疑它是家庭作业)那么出于我能想到的所有实际目的,%stocks哈希应该包含项目的哈希可在每家商店购买

use strict;
use warnings 'all';

my %stocks = (
    storeA => [ qw/ milk eggs / ],
    storeB => [ qw/ milk fruits eggs vegetables / ],
    storeC => [ qw/ milk fruits eggs / ],
);

my @list = qw/ fruits milk eggs /;

my @stores = grep {
    my %stock = map { $_ => 1 } @{ $stocks{$_} };
    grep($stock{$_}, @list) == @list;
} keys %stocks;

use Data::Dump;
dd \@stores;

输出

["storeB", "storeC"]

答案 4 :(得分:0)

更新添加了解释并明确返回子(为清晰起见)

浏览所有商店(键)并检查每个商店元素是否都在键的数组中。

use strict;
use warnings;

my %inventory = (
    storeA => ['milk','eggs'],
    storeB => ['milk','fruits','eggs','vegetables'],
    storeC => ['milk','fruits','eggs'],
);    
my @items = ('fruits', 'milk', 'eggs');

my @found;
foreach my $store (keys %inventory) {
    push @found, $store 
        if @items == grep { in_store($_, $inventory{$store}) } @items
}   

sub in_store { for (@{$_[1]}) { return 1 if $_[0] eq $_ }; return 0; }

print "@found\n";  # prints:  storeB storeC

grep块检查每个项目是否(可用)在商店中,以及传递的数量是否等于商店包含所有项目的项目数量(数组大小)添加。请注意,子例程返回的最后一个值没有显式返回,因此不需要最终的return。为了清楚起见,增加了它。