Создание уникального массива perl
В настоящее время у меня очень простая проблема с получением результата от команды оболочки с обратным тактом. Я извиняюсь, что проблема довольно проста.
У меня есть отсортированный массив (@valid_runs), который, как я знаю, содержит последовательные, повторяющиеся элементы. Я хочу использовать backticks для вывода этого массива в uniq. Я хочу захватить STDOUT в массиве. Я пытаюсь сделать это так.
@unique_valids = `echo '@valid_runs' | uniq`;
print @unique_valids;
Это утверждение для печати ничего не дает. В этом отношении ни один не делает этого.
@unique_valids = `echo '@valid_runs'`;
print @unique_valids;
Я знаю, как использовать uniq и echo. Это кажется довольно странным для меня. Я думаю, что это больше связано с массивами Perl, чем с правильным использованием этих команд. Я искал немного в другом месте, поэтому, пожалуйста, не обижайте меня отрицательными голосами только потому, что решение может показаться тривиальным. Еще раз спасибо за ваше время.
ПРИМЕЧАНИЕ о решениях. Решение TLP является наиболее простым в плане решения уникальной проблемы. Я достаточно гибок, поскольку во всех ответах предлагалось не делать системный вызов для этой проблемы. Если Uniq-функция Perl совпадает с Uniq-Unix, тогда массив должен оставаться отсортированным.
Решение Джона Корбетта работает хорошо, если вас не интересует отсортированный результат.
4 ответа
Использование системных вызовов для чего-то, что может быть легко выполнено с помощью Perl-кода, не очень хорошая идея. Модуль List:: MoreUtils имеет функцию uniq, которая делает то, что вам нужно:
use List::MoreUtils qw(uniq);
my @unique = uniq @runs;
Подпрограмма внутри самого модуля очень проста, точно так же, как и ответ глаубера:
sub uniq (@) {
my %seen = ();
grep { not $seen{$_}++ } @_;
}
Вы должны просто сохранить массив в хэш, потому что ключи хеша всегда уникальны. Вы можете сделать это так:
my %temp_hash = map { $_ => 1 } @valid_runs;
my @unique_valids = keys %temp_hash;
в любом случае это лучший способ сделать это. Здесь нет необходимости использовать обратные тики (я стараюсь избегать их как можно больше).
Это легко сделать в Perl. Вот довольно неясный, но интересный способ дедупликации массива:
@dedup = grep !$seen{$_}++ @orig_array;
Выясните, что это делает, проверив документацию для функции perl grep
,
Если вы должны использовать uniq
Вам, вероятно, нужно поместить каждый элемент массива в отдельную строку.
join("\n", @your_array)
должен достичь этого.
#!/usr/bin/perl
use warnings;
@a = (1, 2, 3, 3, 4, 4, 5);
$cmd = "/usr/bin/uniq <<EOF\n";
$cmd .= $_."\n" foreach (@a);
$cmd .= "EOF\n";
$result = `$cmd`;
print "Cmd: $cmd\n";
print "Result is $result";
@u = split /\n/,$result;
print "After ",join " ",@u,"\n";
Это делает то, что вы спрашиваете, но ответ theglauber все еще лучше Perl.