Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > уникальные элементы массива


Автор: mario315 27.9.2009, 20:42
Добрый вечер. Подскажите, пожалуйста, есть ли какая функция, с помощью которой, можно получить из массива заданное количество уникальных (не повторяющихся) элементов.

Автор: ginnie 27.9.2009, 21:16
Если последовательность не важна, то

Код

my %temp;
for my $elem (@array) {
    $temp{$elem} = 1;
    last if (scalar keys %temp == $count);
}
my @uniq_range = keys %temp;


если последовательность важна, то

Код

my %temp;
my @uniq_range;
for my $elem (@array) {
    unless (exists $temp{$elem}) {
        push(@uniq_range, $elem);
        $temp{$elem} = 1;
        last if (scalar @uniq_range == $count);
    }
}

Автор: DaemonSuw 27.9.2009, 21:16
@mas = (1,2,3,12,3,3,4,4);
$count = 2;
map {$hash{$_}++} @mas;
foreach (keys %hash) { if ($hash{$_} == 1) { print "$_ => $hash{$_}\n" if $count > $i; $i++; }}

Добавлено @ 21:24
ginnie, а если такие условие?
@array = (1,2,3,4,5,1);
$count = 6;
Цитата

my %temp;
for my $elem (@array) {
    $temp{$elem} = 1;
    last if (scalar keys %temp == $count);
}
my @uniq_range = keys %temp;

После отработки 
41325 - хотя 1 - не уникальный элемент



Автор: Pfailed 27.9.2009, 21:29
Код

last if (scalar keys %temp == $count);


А по ресурсам не накладно на каждой итерации вычислять такое выражение, не подскажете? Возможно лучше инкрементную переменную ввести?

Автор: ginnie 27.9.2009, 21:37
DaemonSuw, наверное я неверно понял задачу. Я прочитал "надо получить N уникальных в рамках нового массива элементов".

Автор: ginnie 27.9.2009, 22:05
Pfailed, по идее, scalar keys %temp - должно браться из поля KEYS структуры HV (которая представляет хэш), поэтому не должно негативно влиять на производительность. Как дела обстоят на самом деле - не знаю, надо измерять.

Автор: mario315 27.9.2009, 22:56
Спасибо, ginnie. Спасибо, DaemonSuw. Очень помогли.

Автор: jdoe 29.9.2009, 16:58
use strict;
use warnings;

# takes: $count, $arr_ref
sub uniq {
    my @singles;
    for(@{$_[1]}) {
        do { push(@singles, $_); last if @singles==$_[0] } unless($_ ~~ @singles);
    }
    return @singles;
}

my @source = qw(1 0 1 6 3 3 1 2 4 2 2 1 1 3 4 2 1 3 4 5 6);

$, = ",";
print uniq( 4, \@source); #1,0,6,3
print "\n";
print uniq(-1, \@source); #1,0,6,3,2,4,5
print "\n";
print uniq(50, \@source); #1,0,6,3,2,4,5


Автор: gnatyna 30.9.2009, 09:08
Не экономично, зато писать просто)
Код

my @uniq = splice(@{[(keys %{{ map{+($_=>1)}@not_uniq}})]}, 0, $num);

Автор: amg 30.9.2009, 15:21
Почти классика:
Код
my %seen;
my @uniq = (grep {!$seen{$_}++} @not_uniq)[0..$num-1];


Автор: gnatyna 1.10.2009, 09:58
Цитата(amg @ 30.9.2009,  15:21)
Почти классика:
Код
my %seen;
my @uniq = (grep {!$seen{$_}++} @not_uniq)[0..$num-1];

если $num больше числа уникальных, вернет undefы чтобы заполнить @uniq до $num-1

Автор: amg 1.10.2009, 10:26
Цитата(gnatyna @  1.10.2009,  09:58 Найти цитируемый пост)
если $num больше числа уникальных, вернет undefы чтобы заполнить @uniq до $num-1
Да, это серъезный недостаток кода.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)