У меня есть массив в Perl:
my @my_array = ("one","two","three","two","three");
Как удалить дубликаты из массива?
У меня есть массив в 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
Если вы хотите использовать модуль, попробуйте функцию uniq из List::MoreUtils.
my в этой области, так что все в порядке. При этом, возможно, можно было бы выбрать более описательное имя переменной.
- person ephemient; 18.01.2010
$::a и $::b, не так ли?
- person vol7ron; 21.02.2012
sort использовать нелокальные переменные.
- person Brian Vandenberg; 15.06.2012
sub uniq { my %seen; grep !$seen{$_}++, @_ } — лучшая реализация, поскольку она сохраняет порядок бесплатно. Или, что еще лучше, используйте один из List::MoreUtils.
- person ikegami; 06.11.2012
List::Util имеет uniq , поэтому MoreUtils не понадобится.
- person Sundeep; 30.10.2020
Документация Perl поставляется с хорошей коллекцией часто задаваемых вопросов. Ваш вопрос часто задают:
% perldoc -q duplicate
Ответ, скопированный и вставленный из вывода приведенной выше команды, появится ниже:
Found in /usr/local/lib/perl5/5.10.0/pods/perlfaq4.pod
How can I remove duplicate elements from a list or array?
(contributed by brian d foy)
Use a hash. When you think the words "unique" or "duplicated", think
"hash keys".
If you don't care about the order of the elements, you could just
create the hash then extract the keys. It's not important how you
create that hash: just that you use "keys" to get the unique elements.
my %hash = map { $_, 1 } @array;
# or a hash slice: @hash{ @array } = ();
# or a foreach: $hash{$_} = 1 foreach ( @array );
my @unique = keys %hash;
If you want to use a module, try the "uniq" function from
"List::MoreUtils". In list context it returns the unique elements,
preserving their order in the list. In scalar context, it returns the
number of unique elements.
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
You can also go through each element and skip the ones you've seen
before. Use a hash to keep track. The first time the loop sees an
element, that element has no key in %Seen. The "next" statement creates
the key and immediately uses its value, which is "undef", so the loop
continues to the "push" and increments the value for that key. The next
time the loop sees that same element, its key exists in the hash and
the value for that key is true (since it's not 0 or "undef"), so the
next skips that iteration and the loop goes to the next element.
my @unique = ();
my %seen = ();
foreach my $elem ( @array )
{
next if $seen{ $elem }++;
push @unique, $elem;
}
You can write this more briefly using a grep, which does the same
thing.
my %seen = ();
my @unique = grep { ! $seen{ $_ }++ } @array;
Установите List::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);
@dup_list должно быть внутри вызова uniq, а не @dups
- person incutonez; 11.11.2013
List::Util имеет uniq , поэтому MoreUtils не понадобится.
- person Sundeep; 30.10.2020
Мой обычный способ сделать это:
my %unique = ();
foreach my $item (@myarray)
{
$unique{$item} ++;
}
my @myuniquearray = keys %unique;
Если вы используете хэш и добавляете элементы в хэш. У вас также есть бонус: вы знаете, сколько раз каждый элемент появляется в списке.
foreach цикла: @unique{@myarray}=()
- person Onlyjob; 20.09.2015
Можно сделать с помощью простого однострочного 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.
Блок PFM делает это:
Данные в @in передаются в MAP. MAP создает анонимный хэш. Ключи извлекаются из хэша и передаются в @out
Логика: хэш может иметь только уникальные ключи, поэтому перебирайте массив, присваивайте любое значение каждому элементу массива, сохраняя элемент в качестве ключа этого хеша. Возвращайте ключи хэша, это ваш уникальный массив.
my @unique = keys {map {$_ => 1} @array};
Лучше сделать подпрограмму, если мы должны использовать эту функцию несколько раз в нашем коде.
sub get_unique {
my %seen;
grep !$seen{$_}++, @_;
}
my @unique = get_unique(@array);
List::MoreUtilsuse List::MoreUtils qw(uniq);
my @unique = uniq(@array);
Переменная @array — это список с повторяющимися элементами
%seen=();
@unique = grep { ! $seen{$_} ++ } @array;
Тот последний был довольно хорош. Я бы немного подкорректировал:
my @arr;
my @uniqarr;
foreach my $var ( @arr ){
if ( ! grep( /$var/, @uniqarr ) ){
push( @uniqarr, $var );
}
}
Я думаю, что это, вероятно, самый читаемый способ сделать это.
Предыдущие ответы в значительной степени обобщают возможные способы выполнения этой задачи.
Тем не менее, я предлагаю модификацию для тех, кто не заботится о подсчете дубликатов, но заботится о порядке.
my @record = qw( yeah I mean uh right right uh yeah so well right I maybe );
my %record;
print grep !$record{$_} && ++$record{$_}, @record;
Обратите внимание, что ранее предложенное grep !$seen{$_}++ ... увеличивает $seen{$_} перед отрицанием, поэтому приращение происходит независимо от того, было ли оно уже %seen или нет. Вышеупомянутое, однако, короткое замыкание, когда $record{$_} истинно, оставляя то, что было услышано однажды, «за пределами %record».
Вы также можете пойти на эту нелепость, которая использует автовивификацию и существование хеш-ключей:
...
grep !(exists $record{$_} || undef $record{$_}), @record;
Однако это может привести к некоторой путанице.
И если вас не волнует ни порядок, ни количество дубликатов, вы можете использовать другой хак, используя хеш-фрагменты и трюк, о котором я только что упомянул:
...
undef @record{@record};
keys %record; # your record, now probably scrambled but at least deduped
sub uniq{ my %seen; undef @seen{@_}; keys %seen; } Аккуратно.
- person stevesliva; 09.05.2019
Попробуйте это, кажется, функция uniq нуждается в отсортированном списке для правильной работы.
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";
Выход: а с б д