我想识别具有类似消费选择的客户,并拥有以下购买数据,列出购买各种产品的客户:
$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});
鉴于我有数十种产品可以检查数十个客户端,因此这种迭代效率非常低且非常慢。你能帮我改进一下这个计算吗?
谢谢
答案 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]
...
}
通过这种方式,您可以轻松检查客户端列表中是否有多个产品。
现在你可以做的是,
split
产品字符串并推送列表中的客户
并且对于此列表中的每个产品字符串append
客户端进行拆分
uniq
函数从此列表中获取唯一值列表
醇>
use List::MoreUtils qw(uniq);
或直接使用客户端密钥创建哈希值,并在下次检查密钥是否存在时进行检查
如您所见,将产品添加到每个客户端,您可以通过检查密钥是否存在来执行此操作。