Пользовательский массив сортировать в Perl - PullRequest
6 голосов
/ 30 мая 2010

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

@todos = (
  "1 (A) Complete online final @evm4700 t:2010-06-02",
  "3 Write thank-you t:2010-06-10",
  "4 (B) Clean t:2010-05-30",
  "5 Donate to LSF t:2010-06-02",
  "6 (A) t:2010-05-30 Pick up dry cleaning",
  "2 (C) Call Chris Johnson t:2010-06-01"
);

Это первое число является идентификатором задачи. Если рядом с задачей ([A-Z]), это определяет приоритет задачи. То, что я хочу сделать, это отсортировать массив задач таким образом, чтобы в первую очередь располагались приоритетные элементы (и в порядке убывания приоритета, от A до Z):

@todos = (
  "1 (A) Complete online final @evm4700 t:2010-06-02",
  "6 (A) t:2010-05-30 Pick up dry cleaning",
  "4 (B) Clean t:2010-05-30",
  "2 (C) Call Chris Johnson t:2010-06-01"
  "3 Write thank-you t:2010-06-10",
  "5 Donate to LSF t:2010-06-02",
);

Я не могу использовать обычный sort() из-за этих идентификаторов рядом с задачами, поэтому я предполагаю, что необходима какая-то настраиваемая подпрограмма сортировки. Однако мои знания о том, как сделать это эффективно в Perl, минимальны.

Спасибо всем.

Ответы [ 5 ]

12 голосов
/ 30 мая 2010

Звучит так, как вы хотите преобразование Шварца :

@todos =
    map  { $_->[0] }
    sort { $a->[1] cmp $b->[1] or $a->[0] cmp $b->[0] }
    map  { [ $_, /^\d+ \(([[:alpha:]])\)/ ? $1 : "[" ] }
    @todos;

«[» - символ после «Z»; отдавая этот «приоритет» другим неприоритизованным элементам, они будут отсортированы после приоритетных элементов.

Поочередно и, возможно, легче понять:

@todos =
    map { substr $_, 1 }
    sort
    map { (/^\d+ \(([[:alpha:]])\)/ ? $1 : "[") . $_ }
    @todos;
3 голосов
/ 30 мая 2010

Вот версия, которая довольно явно о том, как это работает:

my @sorted_todos = sort {
    my ($right_prio) = ($b =~ /^\d+\s+\(([A-Z])\)/);
    return -1 unless defined $right_prio;
    my ($left_prio) = ($a =~ /^\d+\s+\(([A-Z])\)/);
    return 1 unless defined $left_prio;
    return $left_prio cmp $right_prio;
} @todos;
0 голосов
/ 02 сентября 2014

Гораздо более простое решение:

sort {($a =~ /\((.)\)/)[0] cmp ($b =~ /\((.)\)/)[0]} @todos;
0 голосов
/ 17 января 2011
use Sort::Key 'keysort';

my @sorted = keysort { /^\d+\s+\(([A-Z])\)/ ? $1 : 'ZZ' } @todos;
0 голосов
/ 30 мая 2010

Здесь исправлено @ решение Шона , которое использует числовую сортировку для идентификаторов задач (таким образом, 10-я задача идет после 9-й, как и должно):

my @sorted_todos =  map  { $_->[0] }
    sort { $a->[1][1] cmp $b->[1][1] # A
                       || 
           $a->[1][0] <=> $b->[1][0] # 1
    } map  { [ $_, /^(\d+) \(([[:alpha:]])\)/ ? [$1, $2] : [0, "zz"]] }  @todos;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...