Perl хэш массива - числовой вид буквенно-цифровых ключей? - PullRequest
1 голос
/ 11 ноября 2011

Я понимаю, что сортировка по умолчанию в perl - это сортировка ASCII, а не числовая. Но как я могу численно отсортировать строки с числами?

Например, у меня есть хэш массивов, например:

myhash{ANN20021015_0101_XML_71.9} = ("anta", "hunna", "huma");
myhash{ANN20021115_0049_XML_14.1} = ("lqd", "qAl", "arrajul");
myhash{ANN20021115_0049_XML_14.2} = ("anna", "alwalada");

Мне просто нужно отсортировать ключи ... но сортировка числовая в строках. Я не могу выполнить сортировку строк, потому что я получаю «10» после «1», но я также не могу выполнить числовую сортировку!

Ответы [ 2 ]

6 голосов
/ 11 ноября 2011

Прежде всего, ваш код не является допустимым Perl и может не выполнять то, что вы думаете.Всегда

  use strict;
  use warnings;

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

  $myhash{'ANN20021015_0101_XML_71.9'} = ["anta", "hunna", "huma"];
  $myhash{'ANN20021115_0049_XML_14.1'} = ["lqd", "qAl", "arrajul"];
  $myhash{'ANN20021115_0049_XML_14.2'} = ["anna", "alwalada"];

Для сортировки по чему-то, кроме целого значения, вы можете преобразовать $a и $b в блоке сортировки и отсортировать результат численно <=> вместо строкового<=>.Этот код делает то, что вам нужно

  my @sorted = sort {
    my ($aa) = $a =~ /.*_(.+)/;
    my ($bb) = $b =~ /.*_(.+)/;
    $aa <=> $bb;
  } keys %myhash;

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

  my @sorted = map  { $_->[0] }
               sort { $a->[1] cmp $b->[1] }
               map  { /.*_(.+)/ and [$_, $1] }
               keys %myhash;
0 голосов
/ 11 ноября 2011

Вам необходимо выполнить пользовательскую сортировку: разрезать строки на части, которые вы знаете, являются литералами / числами, и сравнивать их по мере необходимости.

Из вашего примера это выглядит так, как вы хотите literal. digits, но вы можете изменить регулярное выражение так, чтобы оно подходило вам.

my $cut = qr/(.*?\.)(\d+)(.*)/;
sort { 
    my @a = $a =~ $cut; my @b = $b =~ $cut; 
    $a[0] cmp $b[0] || $a[1] <=> $b[1] || $a[2] cmp $b[2] 
} keys %myhash;

Смотрите также ответ @ Бородина.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...