簡體   English   中英

迭代Perl中所有哈希鍵的組合

[英]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]
    ...
}

這樣,您可以輕松檢查客戶端是否在其列表中包含多個產品。

現在你可以做的是,

  1. split產品字符串並將列表中的客戶端推送

  2. 並且對於每個產品字符串,通過拆分append客戶端append到此列表

  3. 然后使用uniq函數從此列表中獲取唯一值列表

use List::MoreUtils qw(uniq);

或者直接使用客戶端密鑰創建哈希值,並在下一次檢查密鑰是否存在時進行檢查

如您所見,將產品添加到每個客戶端,您可以通過檢查密鑰是否存在來完成此操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM