[英]Iterate through all combinations of hash keys in Perl
我想確定具有類似消費選擇的客戶,並擁有以下購買數據,列出購買各種產品的客戶:
$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});
鑒於我有數十種產品可以檢查數十個客戶端,這種迭代變得非常低效且非常慢。 你能幫我改進一下這個計算嗎?
謝謝
您可以使用Data :: Powerset生成產品的所有子集並迭代它們。 看起來像這樣(未經測試)
use Data::PowerSet 'powerset';
my %Purchase;
my %overlapped;
for my $set ( powerset keys %Purchase ) {
push $overlapped{ join(", ", @$set) }, intersect( @Purchase{ @$set } );
}
我認為不應該將產品作為密鑰,而應該像客戶一樣創建客戶端哈希:
Clients = {
Client1 => [product1, product2, product3, ...]
Client2 => [product1, product2]
Client3 => [product1, product2, product3, product4]
Client4 => [product1]
...
}
這樣,您可以輕松檢查客戶端是否在其列表中包含多個產品。
現在你可以做的是,
split
產品字符串並將列表中的客戶端推送
並且對於每個產品字符串,通過拆分append
客戶端append
到此列表
uniq
函數從此列表中獲取唯一值列表 use List::MoreUtils qw(uniq);
或者直接使用客戶端密鑰創建哈希值,並在下一次檢查密鑰是否存在時進行檢查
如您所見,將產品添加到每個客戶端,您可以通過檢查密鑰是否存在來完成此操作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.