#arrays #perl #count #unique
#массивы #perl #подсчет #уникальный
Вопрос:
Я борюсь с этим уже пару дней и, похоже, не могу в этом разобраться.
У меня есть массив адресов электронной почты, которые были созданы с помощью push(@emails,$email)
цикла while.
Я пытаюсь создать список уникальных доменов с количеством вхождений каждого в массиве.
Упорядочено по количеству вхождений.
Итак, если массив @emails
имеет:
john@yadoo.com ringo@geemail.net george@zoohoo.org paul@yadoo.com
Я могу печатать:
yadoo.com 2
geemail.net 1
zoohoo.org 1
Я нашел этот пример на основе электронных писем в файле, но это выше моего понимания. Может ли кто-нибудь помочь мне в более подробном примере кода, который можно использовать с массивом адресов электронной почты?
perl -e 'while(<>){chomp;/^[^@] @([^@] )$/;$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 рядом с ним. Возможно, я близок?
Комментарии:
1. P.S. Сначала я разделил домены в последних двух приведенных выше примерах, например:
$domain = split('@',$email); push(@domains,$domain);
в цикле, но нужен полный пример, включающий разделение, если необходимо, чтобы не запутать меня еще больше…
Ответ №1:
Вместо того, чтобы давать вам другой ответ, позвольте мне объяснить вам, что делает ваш пример кода:
while(<>){chomp;/^[^@] @([^@] )$/;$h{$1} ;}
foreach $k (sort { $h{$b} <=> $h{$a} } keys %h) {print $h{$k}." ".$k."n";}
В первой строке подсчитываются домены из электронных писем в файлах.
while(<>)
перебирает входные файлы построчно. Входные файлы — это файлы, переданные в качестве аргументов, или stdin, если аргументы не были переданы. Каждая строка помещается в $_
.
chomp;
просто удаляет новую строку с конца $_
.
/^[^@] @([^@] )$/
это регулярное выражение, которое анализирует домен и применяется к $_
. Он проверяет что-то, у чего нет ‘@’ в первой части, затем ‘@’, а затем нет ‘@’ в последней части. Он запоминает последнюю часть, которая будет сохранена в $1
. ^
и $
обозначают начало и конец строки соответственно.
$h{$1} ;
использует домен (в $1
) для увеличения количества в хэше %h
. Это работает, даже если его нет, потому что undef
здесь ведет себя как 0.
Чтобы это работало для вашего списка, вы можете просто сделать
foreach(@emails) {/^[^@] @([^@] )$/;$h{$1} ;}
Вторая строка выводит домены из хэша %h
.
sort { $h{$b} <=> $h{$a} } keys %h
возвращает список доменов, отсортированных по убыванию вхождения, с помощью функции сравнения $h{$b} <=> $h{$a}
для просмотра количества. Обратите внимание, что это b <=> a, а не a <=> b, это делает его убывающим.
Остальная часть строки 2 выводит результат.
Комментарии:
1. Спасибо. Это очень ценно для меня. Спасибо, что нашли время объяснить.
Ответ №2:
Если ваш адрес электронной почты заполнен в массиве, вы получите количество для каждого домена. Я уверен, что кто-то может создать что-то более красивое!
my @emails = ('john@yadoo.com','ringo@geemail.net','george@zoohoo.org','paul@yadoo.com');
my %domainCount;
foreach(@emails){
if ($_ =~ /@(w .*)/){
$domainCount{$1} ;
}
}
for my $domain (sort { $domainCount{$b} <=> $domainCount{$a}} keys %domainCount ){
print "$domain - $domainCount{$domain}n";
}
Комментарии:
1. он говорит: «Упорядочено по количеству вхождений»
2. Теперь сортируем выходные данные в порядке убывания
3. ИДЕАЛЬНО! Как вы делаете это так быстро? Спасибо. Я буду изучать и узнаю, что здесь происходит.
Ответ №3:
Это немного грубо, потому что я устал от Perl, но это должно выполнить свою работу:
use strict;
$|=1;
my ($dom, %hsh);
my @arr = ('john@yadoo.com', 'ringo@geemail.net', 'george@zoohoo.org', 'paul@yadoo.com');
foreach (@arr) {
($dom) = ($_ =~ /.*@(.*)$/);
$hsh{$dom} ;
}
foreach (keys %hsh) {
print ("$_:$hsh{$_}n");
}
Комментарии:
1. Это сработало, но не по порядку, но большое вам спасибо. Помогает мне понять.
2. Просто добавьте ‘сортировать’ непосредственно перед ‘ключами’.
Ответ №4:
Другой вариант:
use strict;
use warnings;
my @array
= qw<john@yadoo.com ringo@geemail.net george@zoohoo.org paul@yadoo.com>
;
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 "@$pairn";
}
Комментарии:
1. ключи — это домены здесь, нет смысла их сортировать, я предполагаю, что вы хотели использовать сортировку с помощью <=>
2. Спасибо, это тоже работает, но не перечислено по порядку. Очень хорошо и использует map, который показывает мне, как это сделать! Какой полезный опыт! Спасибо!