迭代Perl中所有哈希键的组合

时间:2014-01-09 12:37:01

标签: perl hash key

我想识别具有类似消费选择的客户,并拥有以下购买数据,列出购买各种产品的客户:

$product1 = qw/client1 client2 client3 client4/;
$product2 = qw/client2 client4/;
$product3 = qw/client3 client4/;
$product4 = qw/client1 client5/;
$product5 = qw/client1/;

我认为创建一个以产品为关键,客户端为值的哈希可能是一个好主意。

%Purchase;
$Purchase{$product} = @clients;

现在我需要比较所有可能的产品组合,看看是否有一些重叠的客户:

    my @overlapped12 = intersect($Purchase{$product1}, $Purchase{$product2}); # 2 products 
    my @overlapped13 = intersect($Purchase{$product1}, $Purchase{$product3}); # 2 products 
    [...]
    my @overlapped123 = intersect($Purchase{$product1}, $Purchase{$product2}, $Purchase{$product3); # 3 products
[...]
my @overlapped12345 = intersect($Purchase{$product1},$Purchase{$product2},$Purchase{$product3},$Purchase{$product4},$Purchase{$product5});

鉴于我有数十种产品可以检查数十个客户端,因此这种迭代效率非常低且非常慢。你能帮我改进一下这个计算吗?

谢谢

2 个答案:

答案 0 :(得分:2)

您可以使用Data::Powerset生成产品的所有子集并迭代它们。它看起来像这样(未经测试)

use Data::PowerSet 'powerset';

my %Purchase;
my %overlapped;  

for my $set ( powerset keys %Purchase ) {
    push $overlapped{ join(", ", @$set) }, intersect( @Purchase{ @$set } );
}

答案 1 :(得分:0)

我认为不应该将产品作为密钥,而应该像客户端一样创建哈希:

Clients = {
    Client1 => [product1, product2, product3, ...]
    Client2 => [product1, product2]
    Client3 => [product1, product2, product3, product4]
    Client4 => [product1]
    ...
}

通过这种方式,您可以轻松检查客户端列表中是否有多个产品。

现在你可以做的是,

  1. split产品字符串并推送列表中的客户

  2. 并且对于此列表中的每个产品字符串append客户端进行拆分

  3. 然后使用
  4. 中的uniq函数从此列表中获取唯一值列表

    use List::MoreUtils qw(uniq);

    或直接使用客户端密钥创建哈希值,并在下次检查密钥是否存在时进行检查

    如您所见,将产品添加到每个客户端,您可以通过检查密钥是否存在来执行此操作。