Подтвердить что ты не робот

Как распечатать уникальные элементы в массиве Perl?

Я вставляю элементы в массив во время инструкции while. Каждый элемент является именем учителя. В конце концов заканчивается дублирование имен учителей в массиве, когда цикл завершается. Иногда они не находятся рядом друг с другом в массиве, иногда они есть.

Как я могу напечатать только уникальные значения в этом массиве после того, как он закончил получать значения, введенные в него? Без необходимости анализировать весь массив каждый раз, когда я хочу напечатать элемент.

Получает код после того, как все было перенесено в массив:

$faculty_len = @faculty;
$i=0;
while ($i != $faculty_len)
{
        printf $fh '"'.$faculty[$i].'"';
        $i++;
}   
4b9b3361

Ответ 1

use List::MoreUtils qw/ uniq /;
my @unique = uniq @faculty;
foreach ( @unique ) {
    print $_, "\n";
}

Ответ 2

Лучше всего использовать встроенный инструмент (в основном), например uniq (как описано innaM).

Если у вас нет возможности использовать uniq и вы хотите сохранить порядок, вы можете использовать grep для имитации этого.

my %seen;
my @unique = grep { ! $seen{$_}++ } @faculty;
# printing, etc.

Это сначала дает вам хэш, где каждый ключ является каждой записью. Затем вы перебираете каждый элемент, подсчитываете, сколько из них есть, и добавляете первый. (Обновлено с комментариями brian d foy)

Ответ 3

Я предлагаю вставить его в хэш. например:

my %faculty_hash = ();
foreach my $facs (@faculty) {
  $faculty_hash{$facs} = 1;
}
my @faculty_unique = keys(%faculty_hash);

Ответ 4

@array1 = ("abc", "def", "abc", "def", "abc", "def", "abc", "def", "xyz");

@array1 = grep { ! $seen{ $_ }++ } @array1;

print "@array1\n"; 

Ответ 5

На этот вопрос отвечает множество решений в perldoc. Просто введите в командной строке:

perldoc -q duplicate

Ответ 6

Обратите внимание: некоторые ответы, содержащие хэш, изменят порядок массива. Хэши не имеют никакого порядка, поэтому получение ключей или значений сделает список с заказом undefined.

Это не относится к grep { ! $seen{$_}++ } @faculty

Ответ 7

Это одна команда liner для печати уникальных строк, чтобы она появилась.

perl -ne '$seen{$_}++ || print $_' fileWithDuplicateValues

Ответ 8

Я только что нашел избитый 3 лайнер, наслаждаюсь

my %uniq; 
undef @uniq(@non_uniq_array); 
my @uniq_array = keys %uniq; 

Ответ 9

Еще один способ сделать это полезен, только если вам не нужен порядок:

my %hash;
@hash{@faculty}=1;
my @unique=keys %hash;

Если вы хотите избежать объявления новой переменной, вы можете использовать недооцененную глобальную переменную % _

@_{@faculty}=1;
my @unique=keys %_;

Ответ 10

Если вам нужно обработать список факультетов любым способом, карта над массивом, преобразованная в хэш для коалесцирования ключей, а затем сортировка ключей - это еще один хороший способ:

my @deduped = sort keys %{{ map { /.*/? ($_,1):() } @faculty }};
print join("\n", @deduped)."\n";

Вы обрабатываете список, изменяя регулярное выражение /.*/ для выбора или синтаксического анализа и захвата соответственно, и вы можете выводить один или несколько мутированных, не уникальных ключей за проход, делая ($_,1):() произвольно сложным.

Если вам нужно изменить данные в полете с помощью регулярного выражения подстановки, скажем, чтобы удалить точки из имен (s/\.//g), тогда подстановка в соответствии с приведенным выше шаблоном будет мутировать исходный массив @faculty из-за $_ сглаживание. Вы можете обойти сглаживание $_, сделав анонимную копию массива @faculty (см. Так называемый оператор "детская тележка" )

my @deduped = sort keys %{{ map {/.*/? do{s/\.//g; ($_,1)}:()} @{[ @faculty ]} }};
print join("\n", @deduped)."\n";
print "Unmolested array:\n".join("\n", @faculty)."\n";

В более поздних версиях Perl вы можете передать keys hashref, и вы можете использовать неразрушающую замену:

my @deduped = sort keys { map { /.*/? (s/\.//gr,1):() } @faculty };

В противном случае предпочтительными могут быть решения grep или $seen[$_]++ в другом месте.