2011-05-11 8 views
1

我一直在爲此奮鬥了幾天,似乎無法弄清楚。Perl - 如何計算和打印電子郵件地址數組中域的出現次數?

我有一個通過push(@emails,$email)在一個while循環中創建的電子郵件地址數組。

我正在嘗試創建數組中每個出現計數爲的唯一域的列表。

按發生次數排序。

所以,如果陣列@emails有:

[email protected] [email protected] [email protected] [email protected]

我可以打印:

yadoo.com 2 
geemail.net 1 
zoohoo.org 1 

我發現基於文件中的電子郵件,但,路在我頭上這個例子。有人可以幫助我一個更詳細的代碼示例,可用於一組電子郵件地址?

perl -e 'while(<>){chomp;/^[^@][email protected]([^@]+)$/;$h{$1}++;} 
foreach $k (sort { $h{$b} <=> $h{$a} } keys %h) {print $h{$k}." ".$k."\n";} infile 

我也試過:(更多我的缺乏理解)

foreach my $domain (sort keys %$domains) { 
    print "$domain"."="; 
    print $domains->{$domain}."\n"; 
}; 

my %countdoms; 
$countdoms{$_}++ for @domains; 
print "$_ $countdoms{$_}\n" for keys %countdoms; 

我有很多不同的嘗試最好的結果是總計數(這是1812(準確計數),旁邊有一個數字2,我很接近,可能嗎?

+0

P.S.我在上面的兩個例子中首先將域分割出來,例如:'$ domain = split('\ @',$ email);推(@域,$域);'在一個循環,但是,需要完整的例子,包括如果需要分裂,以避免更多的混淆我... – Stephayne 2011-05-11 13:58:33

回答

1

如果你有你的電子郵件地址在一個數組中填充,這會讓你爲每個域計數。我確定有人可以製作更漂亮的東西!

my @emails = ('[email protected]','[email protected]','[email protected]','[email protected]'); 

my %domainCount; 

foreach(@emails){ 
    if ($_ =~ /@(\w+.*)/){ 
     $domainCount{$1}++; 
    } 
} 

for my $domain (sort { $domainCount{$b} <=> $domainCount{$a}} keys %domainCount){ 
    print "$domain - $domainCount{$domain}\n"; 
} 
+0

他說:「按發生次數排序」 – snoofkin 2011-05-11 14:07:16

+0

哎呦!更新 – beresfordt 2011-05-11 14:15:16

+0

現在按照降序排列輸出 – beresfordt 2011-05-11 14:21:34

0

這是一個有點粗,因爲我是生鏽的Perl的,但這應該做的工作:

use strict; 
$|=1; 
my ($dom, %hsh); 
my @arr = ('[email protected]', '[email protected]', '[email protected]', '[email protected]'); 
foreach (@arr) { 
    ($dom) = ($_ =~ /.*\@(.*)$/); 
    $hsh{$dom}++; 
} 
foreach (keys %hsh) { 
    print ("$_:$hsh{$_}\n"); 
} 
+0

沒有必要逃脫@ – snoofkin 2011-05-11 14:05:05

+0

這工作,但不是爲了,但非常感謝你。幫助我理解。 – Stephayne 2011-05-11 14:32:23

+0

只需在「按鍵」之前添加「排序」即可。 – blankabout 2011-05-11 15:52:08

0

另一個變化:

use strict; 
use warnings; 

my @array 
    = qw<[email protected] [email protected] [email protected] [email protected]> 
    ; 
my %dom_count; 
$dom_count{ $_ }++ foreach map { (split '@')[-1] } @array; 
foreach my $pair ( 
    sort { $b->[1] <=> $a->[1] or $a->[0] cmp $b->[0] } 
    map { [ $_ => $dom_count{ $_ } ] } keys %dom_count 
    ) { 
    print "@$pair\n"; 
} 
+0

鍵是這裏的域名,沒有排序他們的感覺,我想你想用排序與<=> – snoofkin 2011-05-11 14:22:39

+0

謝謝,這工作,但沒有列出的順序。非常好,並使用地圖,告訴我如何做到這一點!什麼是學習體驗!謝謝! – Stephayne 2011-05-11 14:36:24

2

而不是給你一個答案,讓我向您解釋您的代碼示例正在做什麼:

while(<>){chomp;/^[^@][email protected]([^@]+)$/;$h{$1}++;} 
foreach $k (sort { $h{$b} <=> $h{$a} } keys %h) {print $h{$k}." ".$k."\n";} 

第一行從文件中的電子郵件中統計域。

while(<>)逐行重複輸入文件。輸入文件是作爲參數或標準輸入傳遞的文件(如果沒有參數傳遞的話)。每行放置在$_

chomp;只是從$_末尾刪除換行符。

/^[^@][email protected]([^@]+)$/是解析出域的正則表達式,適用於$_。它檢查在第一部分沒有'@'的東西,然後是'@',然後在最後一部分沒有'@'。它記得最後一部分,它將存儲在$1^$分別代表字符串的開始和結束。

$h{$1}++;使用域(在$1中)來增加散列%h中的計數。這工作即使它不存在,因爲undef行爲很喜歡這裏0

爲了使這項工作對你的列表,你可以做

foreach(@emails) {/^[^@][email protected]([^@]+)$/;$h{$1}++;} 

第二行顯示出這個哈希%h域。

sort { $h{$b} <=> $h{$a} } keys %h返回按降序排列的域列表,使用比較函數$h{$b} <=> $h{$a}查找計數。請注意,這是b < => a,而不是< => b,這使得它下降。

第2行的其餘部分打印出結果。

HTH。

+0

謝謝。這對我很有價值。感謝您花時間解釋。 – Stephayne 2011-05-11 17:11:43

相關問題