Как я могу удалить дубликаты и сортировку одновременно в Perl? - PullRequest
0 голосов
/ 09 сентября 2010

У меня есть массив такого типа

@uniqarr = qw(error 0 goodrecordno:6123, error 0 goodrecordno:6143, error 1 goodrecordno:10245, error 1 goodrecordno:10678, error 1 goodrecordno:10698, error 2 goodrecordno:16245, error 2 goodrecordno:16123);

Я хочу o / p как

error 0 goodrecordno:6123
error 1 goodrecordno:10245 
error 2 goodrecordno:16123

Т.е. каждая ошибка один раз с соответствующим наименьшим номером записи. Может кто-нибудь помочь мне без использования модулей cpan

Заранее спасибо.

Ответы [ 3 ]

3 голосов
/ 09 сентября 2010

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

foreach my $number ( sort { $a <=> $b } keys %lowest ) {
    print "error $number goodrecordno:$lowest{$number}\n";
    };

Это дает вам вывод, который вы искали:

error 0 goodrecordno:6123
error 1 goodrecordno:10245
error 2 goodrecordno:16123

Это базовый шаблон для такого рода проблем.Шаг 1: отсканируйте данные, чтобы запомнить, что вы хотите, используя хеш для ввода этих данных.Шаг 2: вывести содержимое хеша.

1 голос
/ 09 сентября 2010

Для удаления дубликатов лучше всего использовать List :: MoreUtils 'uniq,:

use List::MoreUtils 'uniq';
my @unique_list = uniq @list;

или без CPAN (хотя это редко требуется):

my %values;
@values{@list} = ();
my @unique_list = keys %values;

Вы можете отсортировать любой список, используя встроенную функцию sort - см. perldoc -f sort и perldoc -q 'Как отсортировать массив' .


Кстати, данные, которые вы указали, не соответствуют описанному вами поведению. Если вы объявите массив как

@uniqarr = qw(error 0 goodrecordno:6123, error 0 goodrecordno:6143, error 1 goodrecordno:10245, error 1 goodrecordno:10678, error 1 goodrecordno:10698, error 2 goodrecordno:16245, error 2 goodrecordno:16123);

... тогда его содержимое будет содержать:

(
  'error',
  '0',
  'goodrecordno:6123,',
  'error',
  '0',
  'goodrecordno:6143,',
  'error',
  '1',
  'goodrecordno:10245,',
  'error',
  '1',
  'goodrecordno:10678,',
  'error',
  '1',
  'goodrecordno:10698,',
  'error',
  '2',
  'goodrecordno:16245,',
  'error',
  '2',
  'goodrecordno:16123'
);

Что вам нужно сделать, это прочитать данные в хеш-таблицу , а затем проанализировать в соответствии с вашими критериями. Я не могу идти дальше, так как не совсем понятно, что вы ищете. Пожалуйста, прочтите perldoc perldata и perldoc perldsc , чтобы узнать больше о структурах данных Perl.

0 голосов
/ 09 сентября 2010

Как уже все отметили, ваша первая проблема в том, что qw() не подходит для установки этого массива.

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


@uniqarr = (
  { error => 0, goodrecordno => 6123, },
  { error => 0, goodrecordno => 6143, },
  { error => 1, goodrecordno => 10245, },
  { error => 1, goodrecordno => 10678, },
  { error => 1, goodrecordno => 10698, },
  { error => 2, goodrecordno => 16245, },
  { error => 2, goodrecordno => 16123, },
);

Затем, чтобы извлечь каждый экземпляр ошибки с наименьшим goodrecordno, мы можем сделать следующее.

Сначала мы импортируем min из List :: Util. Этот модуль является основным Perl и не требует CPAN.

Затем реструктурируйте вход @uniqarr. Намного проще сгруппировать по значениям ошибок. Так что by_error - это хэш массивов. Ключом хэша является значение ошибки, массив содержит все значения goodrecordno.

Наконец мы получаем желаемый результат. Цикл по хешу означает, что мы перебираем каждое значение ошибки, отсортированное для обеспечения правильного порядка вывода. Затем мы извлекаем минимальное хорошее значение. Что просто оставляет печать вывода.


use List::Util qw(min); # In core Perl, not CPAN

# Restructure input
my %by_error; # Hash with error as key, array of goodrecordno as value.
foreach (@uniqarr) {
  push @{$by_error{$_->{error}}}, $_->{goodrecordno};
}

# Output as desired
foreach my $error (sort keys %by_error) {
  my $min_no = min @{$by_error{$error}};
  print "error $error goodrecordno:$min_no\n";
}
...