Как распечатать уникальные элементы в массиве Perl? - PullRequest
25 голосов
/ 13 января 2009

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

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

Вот код после того, как все было помещено в массив:

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

Ответы [ 10 ]

42 голосов
/ 13 января 2009
use List::MoreUtils qw/ uniq /;
my @unique = uniq @faculty;
foreach ( @unique ) {
    print $_, "\n";
}
33 голосов
/ 13 января 2009

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

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

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

Сначала вы получите хеш, в котором каждый ключ является каждой записью. Затем вы перебираете каждый элемент, подсчитываете их количество и добавляете первый. (Обновлено с комментариями Брайана Д. Фоя)

14 голосов
/ 13 января 2009

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

my %faculty_hash = ();
foreach my $facs (@faculty) {
  $faculty_hash{$facs} = 1;
}
my @faculty_unique = keys(%faculty_hash);
5 голосов
/ 25 июля 2012

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

perldoc -q duplicate
5 голосов
/ 02 апреля 2012
@array1 = ("abc", "def", "abc", "def", "abc", "def", "abc", "def", "xyz");

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

print "@array1\n"; 
4 голосов
/ 01 октября 2013

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

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

3 голосов
/ 08 декабря 2011

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

perl -ne '$seen{$_}++ || print $_' fileWithDuplicateValues
2 голосов
/ 01 октября 2013

Просто еще один способ сделать это, полезно , только если вы не заботитесь о заказе :

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

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

@_{@faculty}=1;
my @unique=keys %_;
2 голосов
/ 09 ноября 2011

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

my %uniq; 
undef @uniq(@non_uniq_array); 
my @uniq_array = keys %uniq; 
0 голосов
/ 18 июня 2014

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

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

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

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

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 хэш-ссылку и использовать неразрушающую замену:

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

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

...