Создание уникального массива perl

В настоящее время у меня очень простая проблема с захватом вывода команды оболочки с обратной галочкой. Прошу прощения, что проблема довольно простая.

У меня есть отсортированный массив (@valid_runs), который, как я знаю, содержит последовательные повторяющиеся элементы. Я хочу использовать обратные кавычки, чтобы повторить этот массив в uniq. Я хочу захватить STDOUT в массиве. Я пытаюсь сделать это так.

@unique_valids = `echo '@valid_runs' | uniq`;
print @unique_valids;

Этот оператор печати ничего не дает. Если на то пошло, это тоже не так.

@unique_valids = `echo '@valid_runs'`;
print @unique_valids;

Я знаю, как использовать uniq и эхо. Мне это кажется довольно странным. Я думаю, что это больше связано с массивами perl, чем с правильным использованием этих команд. Я искал немного в другом месте, поэтому, пожалуйста, не забрасывайте меня отрицательными голосами только потому, что решение может показаться тривиальным. Еще раз спасибо за ваше время.

ПРИМЕЧАНИЕ о решениях: решение TLP является наиболее простым в плане решения проблемы uniq. Я проявляю гибкость, поскольку во всех ответах предлагалось не выполнять системный вызов для решения этой проблемы. Если функция uniq в Perl такая же, как и в Unix, то массив должен оставаться отсортированным.

Решение Джона Корбетта хорошо работает, если вам не нужен отсортированный результат.


person order    schedule 03.08.2012    source источник
comment
одна потенциальная проблема: заканчиваются ли элементы @valid_runs новой строкой? в противном случае echo выдаст только одну строку вывода в качестве входных данных для uniq.   -  person ErikR    schedule 03.08.2012
comment
вы уверены, что @valid_runs не пусто? это что-то печатает для меня: @x=(3,2,1);@y = `echo '@x'`;print @y;   -  person ErikR    schedule 03.08.2012
comment
@ user5402 Я уверен, что @valid run не пуст. Я уверен, что каждая запись имеет новую строку в конце строки. Ваш пример работает. Что приятно; показывает мне, что я не предлагаю ничего слишком сумасшедшего. Вот фрагмент @valid_runs: /raid1/home/pharmacy/morguna/1experiments_copy/1experiments/test10-10/run36415 /raid1/home/pharmacy/morguna/1experiments_copy/1experiments/test10-10/run36415 /raid1/home/pharmacy/morguna/1experiments_copy/1experiments/test10-10/run36416 /raid1/home/pharmacy/morguna/1experiments_copy/1experiments/test10-10/run36416   -  person order    schedule 03.08.2012
comment
Обсуждение всевозможных вещей, которые вы, возможно, захотите сделать с массивами в Perl, например, определение разницы между двумя массивами, см. в FAQ по Perl: perldoc.perl.org/perlfaq4.html#Data:-Arrays   -  person Andy Lester    schedule 04.08.2012


Ответы (4)


Использование системных вызовов для чего-то, что может быть легко выполнено с помощью кода Perl, не является хорошей идеей. В модуле List::MoreUtils есть уникальная функция, которая делает то, что вам нужно:

use List::MoreUtils qw(uniq);

my @unique = uniq @runs;

Однако подпрограмма внутри самого модуля очень проста, как и ответ Глаубера:

sub uniq (@) {
    my %seen = ();
    grep { not $seen{$_}++ } @_;
}
person TLP    schedule 03.08.2012
comment
Да, для текущего решения я просто реализую что-то в Perl. Делать ненужные системные вызовы плохо. Мне просто было лень, так как я уже знал об uniq. Спасибо за ваше время. - person order; 04.08.2012

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

my %temp_hash = map { $_ => 1 } @valid_runs;
my @unique_valids = keys %temp_hash;

это perl способ сделать это в любом случае. Здесь нет необходимости использовать задние тики (я стараюсь избегать их, насколько могу).

person John Corbett    schedule 03.08.2012
comment
Это не сохраняет порядок массива. - person stark; 03.08.2012
comment
он не сказал, что это нужно сохранить - person John Corbett; 03.08.2012
comment
В этом контексте это не обязательно, однако я хочу иметь возможность сделать что-то настолько простое, как добавить массив в команды оболочки. @JohnCorbett Спасибо за ваше решение. Он достигает того, что нужно сделать, но я все еще хочу знать, как сделать то, что я предложил. - person order; 03.08.2012

Это легко сделать в Perl. Вот довольно неясный, но забавный способ дедупликации массива:

@dedup = grep !$seen{$_}++ @orig_array;

Выясните, что это делает, проверив документацию Perl-функции grep.

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

join("\n", @your_array)

должен добиться этого.

person theglauber    schedule 03.08.2012

#!/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";

Это делает то, что вы просите, но ответ Глаубера все же лучше Perl.

person stark    schedule 03.08.2012