У меня есть массив в Perl:
my @my_array = ("one","two","three","two","three");
Как я могу удалить дубликаты из массива?
Вы можете сделать что-то подобное, как показано в perlfaq4:
sub uniq {
my %seen;
grep !$seen{$_}++, @_;
}
my @array = qw(one two three two three);
my @filtered = uniq(@array);
print "@filtered\n";
Выходы:
one two three
Если вы хотите использовать модуль, попробовать функцию уник
из списка :: MoreUtils
В документации Perl поставляется с хорошим набором часто задаваемые вопросы. Ваш вопрос Часто задаваемые:
% perldoc -q duplicate
Ответ, скопировать и вставить из вывода команды выше, приводится ниже:
в <предварительно>, который находится в /usr/местные/библиотека lib/perl5/5.10.0/чалды/perlfaq4.РМО Как я могу удалить повторяющиеся элементы из списка или массива? (вклад Брайан Д Фой)
Использовать хэш. Если вы считаете, что слова на "уникальный" или "дублирует" и, думаю, на "хэш-ключи и".
Если вы Don'т волнует порядок элементов, вы могли бы просто создать хэш, затем извлеките ключи. Это's не важно, как вы создать хэш: только что вы используете на "Ключи", чтобы сделать уникальные элементы.
my %hash = map { $_, 1 } @array;
# or a hash slice: @hash{ @array } = ();
# or a foreach: $hash{$_} = 1 foreach ( @array );
my @unique = keys %hash;
Если вы хотите использовать модуль, попробовать в "уник" и функция от "в список::MoreUtils-то". В контексте списка он возвращает уникальные элементы, сохраняя их порядок в списке. В скалярном контексте она возвращает количество уникальных элементов.
use List::MoreUtils qw(uniq);
my @unique = uniq( 1, 2, 3, 4, 4, 5, 6, 5, 7 ); # 1,2,3,4,5,6,7
my $unique = uniq( 1, 2, 3, 4, 4, 5, 6, 5, 7 ); # 7
Вы также можете пройти через каждый элемент и пропустить те, что вы'вэ видел прежде чем. Использовать хеш-код для отслеживания. Первый раз петлю видит элемент, этот элемент имеет ключевое значение в %Видел. В "Следующий" и оператор создает ключ и сразу же использует ее стоимости, что есть "Оно" и, таким образом петлю продолжается в "толчок" и увеличивает значение для этого ключа. Следующий время цикла видит того же элемента, его ключ существует в хэш и значение для этого ключа является истиной (поскольку она's не 0 или "Оно", У), поэтому следующий пропускает итерацию, и цикл переходит к следующему элементу.
my @unique = ();
my %seen = ();
foreach my $elem ( @array )
{
next if $seen{ $elem }++;
push @unique, $elem;
}
Вы можете писать более коротко, используя grep, которая делает то же самое вещь.
my %seen = ();
my @unique = grep { ! $seen{ $_ }++ } @array;
</пред>
Установите список::MoreUtils из CPAN
Тогда в ваш код:
use strict;
use warnings;
use List::MoreUtils qw(uniq);
my @dup_list = qw(1 1 1 2 3 4 4);
my @uniq_list = uniq(@dup_list);
Обычный способ сделать это:
my %unique = ();
foreach my $item (@myarray)
{
$unique{$item} ++;
}
my @myuniquearray = keys %unique;
Если вы используете хэш и добавить элементы в хэш. У вас также есть бонус зная, сколько раз каждый элемент отображается в списке.
Переменной @массива является список с повторяющимися элементами
%seen=();
@unique = grep { ! $seen{$_} ++ } @array;
Может быть сделано с простой Perl и один вкладыш.
my @in=qw(1 3 4 6 2 4 3 2 6 3 2 3 4 4 3 2 5 5 32 3); #Sample data
my @out=keys %{{ map{$_=>1}@in}}; # Perform PFM
print join ' ', sort{$a<=>$b} @out;# Print data back out sorted and in order.
ПФМ блока это:
Данные в @в подается в карте. Карта строит анонимный хэш. Ключи извлекаются из хэша и кормить в @ВНЕ
Это последнее было довольно хорошо. Я'd, просто настроить его немного:
my @arr;
my @uniqarr;
foreach my $var ( @arr ){
if ( ! grep( /$var/, @uniqarr ) ){
push( @uniqarr, $var );
}
}
Я думаю, это, наверное, самый четкий способ сделать это.
Логика: хэш может иметь только уникальные ключи, чтобы выполнить итерации по массиву присвоить любое значение каждому элементу массива, сохраняя элемент как ключ хэша. Вернуть ключи хэш, его свой уникальный набор.
my @unique = keys {map {$_ => 1} @array};
Лучше сделать подпрограмму, если мы должны использовать эту функцию несколько раз в наш код.
sub get_unique {
my %seen;
grep !$seen{$_}++, @_;
}
my @unique = get_unique(@array);
use List::MoreUtils qw(uniq);
my @unique = uniq(@array);
Предыдущие ответы очень сильно обобщить возможные пути решения этой задачи.
Однако, я предлагаю модификация для тех, кто _don'быть, с заботой о counting дубликаты, но до заботиться о порядке.
my @record = qw( yeah I mean uh right right uh yeah so well right I maybe );
my %record;
print grep !$record{$_} && ++$record{$_}, @record;
Отметим, что ранее предложил грэп !$видел{$_}++ ...
шагом $видел{$_}
перед отрицанием, так как приращение происходит независимо от того, уже %видел или нет. Выше, однако, при коротких замыканиях, когда
$запись{$_}истинно, и то, что'ы были когда-то слышал 'С
%запись`'.
Вы можете также перейти к этой нелепости, которая использует autovivification и наличие хэш-ключи:
...
grep !(exists $record{$_} || undef $record{$_}), @record;
Что, впрочем, может привести к некоторой путанице.
И если вы заботитесь о ни порядка, или дублировать граф, вы могли бы еще взломать, используя хэш-фрагмент, а также уловка, которую я только что упомянул:
...
undef @record{@record};
keys %record; # your record, now probably scrambled but at least deduped
Попробуйте это, кажется, функция уник нужен отсортированный список, чтобы работать должным образом.
use strict;
# Helper function to remove duplicates in a list.
sub uniq {
my %seen;
grep !$seen{$_}++, @_;
}
my @teststrings = ("one", "two", "three", "one");
my @filtered = uniq @teststrings;
print "uniq: @filtered\n";
my @sorted = sort @teststrings;
print "sort: @sorted\n";
my @sortedfiltered = uniq sort @teststrings;
print "uniq sort : @sortedfiltered\n";
Используя концепцию уникального хэш-ключи :
my @array = ("a","b","c","b","a","d","c","a","d");
my %hash = map { $_ => 1 } @array;
my @unique = keys %hash;
print "@unique","\n";
Выход: а с б д