Интересным спином в этом вопросе является uniq -u
!Я не думаю, что другие ответы, которые я видел, касаются этого;они имеют дело с sort -u example.txt
или (несколько расточительно) sort example.txt | uniq
.
Разница в том, что опция -u
устраняет все вхождения дублированных строк, поэтому на выходе выводятся строки, которые появляются только один раз.
Чтобы решить эту проблему, вам нужно знать, сколько раз каждое имя появляется, а затем вам нужно напечатать имена, которые появляются только один раз.Предполагая, что список должен быть прочитан из стандартного ввода, тогда этот код делает трюк:
my %counts;
while (<>)
{
chomp;
$counts{$_}++;
}
foreach my $name (sort keys %counts)
{
print "$name\n" if $counts{$name} == 1;
}
Или, используя grep
:
my %counts;
while (<>)
{
chomp;
$counts{$_}++;
}
{
local $, = "\n";
print grep { $counts{$_} == 1 } sort keys %counts;
}
Или, если вы ненеобходимо удалить символы новой строки (потому что вы собираетесь печатать только имена):
my %counts;
$counts{$_}++ for (<>);
print grep { $counts{$_} == 1 } sort keys %counts;
Если вы действительно хотите, чтобы каждое имя, которое появляется на входе, появлялось на выходе (но только один раз)), тогда любое из других решений сделает свое дело (или, с минимальной адаптацией, сделает свое дело).Фактически, поскольку строки ввода заканчиваются символом новой строки, вы можете сгенерировать ответ всего в двух строках:
my %counts = map { $_, 1 } <>;
print sort keys %counts;
Нет, вы не можете сделать это в одной, просто заменив %counts
вprint
строка с map
в первой строке:
print sort keys map { $_, 1 } <>;
Вы получаете ошибку:
Type of arg 1 to keys must be hash or array (not map iterator) at ...