Как переупорядочить элементы списка в Perl - PullRequest
1 голос
/ 03 апреля 2019

У меня есть список в Perl.

@alist=("a_vld","a_sf","a_ef","a_val");
print join(',', @alist), "\n";

Выход:

a_vld,a_sf,a_ef,a_val

Как я могу изменить порядок элементов в списке так, чтобы его выходные данные были такими, как ожидалось:

a_sf,a_ef,a_vld,a_val

Примечание: a_ будет меняться с разными строками, но я хочу сохранить порядок sf,ef,vld,val

Ответы [ 3 ]

6 голосов
/ 03 апреля 2019

Один из способов упорядочить (отсортировать) по данному набору - связать числовой порядок с его элементами.

Затем нам нужно найти эти ключи в строках в списке для сортировки.Это делается один раз, перед фактической сортировкой, через преобразование Шварца.

use List::Util qw(first);

my @alist = ("a_vld", "a_sf", "a_ef", "a_val");

my @keys = qw(sf ef vld val);                       # keys to sort by
my %order_by = map { $keys[$_] => $_ } 0..$#keys;

my @sorted = 
    map { $_->[0] }
    sort { $order_by{$a->[1]} <=> $order_by{$b->[1]} }
    map {
        my $elem = $_;
        [ $elem, first { $elem =~ /$_/ } keys %order_by ]
    }
    @alist;

say "@sorted";

Это печатает строку: a_sf a_ef a_vld a_val

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

5 голосов
/ 03 апреля 2019

Для краткого списка используйте функцию сортировки, которая идентифицирует последовательности в порядке

@sorted = sort {
    ($b =~ /sf$/) <=> ($a =~ /sf$/)
        || ($b =~ /ef$/) <=> ($a =~ /ef$/)
        || ($b =~ /vld$/) <=> ($a =~ /vld$/)
        || ($b =~ /val$/) <=> ($a =~ /val$/)
} @alist;
3 голосов
/ 03 апреля 2019

Если перед кодом всегда стоит _, а код всегда в конце

use Sort::Key qw( ikeysort );

my @order = qw( sf ef vld val );
my %order = map { $order[$_] => $_ } 0..$#order;

my @sorted = ikeysort { /_([^_\W]+)\z/ ? $order{$1} : 0 } @unsorted;

Выше приведена более быстрая и понятная версия следующего:

my @order = qw( sf ef vld val );
my %order = map { $order[$_] => $_ } 0 .. $#order;

my @sorted =
   sort {
      my $key_a = /_([^_\W]+)\z/ ? $order{$1} : 0;
      my $key_b = /_([^_\W]+)\z/ ? $order{$1} : 0;
      $key_a <=> $key_b || $a cmp $b
   }
      @unsorted;

В противном случае

use Sort::Key qw( ikeysort );

my @order = qw( sf ef vld val );
my %order = map { $order[$_] => $_ } 0..$#order;
my $alt = join '|', map quotemeta, @order;
my $re = qr/($alt)/;

my @sorted = ikeysort { /$re/ ? $order{$1} : 0 } @unsorted;

Выше приведена более быстрая и понятная версия следующего:

my @order = qw( sf ef vld val );
my %order = map { $order[$_] => $_ } 0..$#order;
my $alt = join '|', map quotemeta, @order;
my $re = qr/($alt)/;

my @sorted =
   sort {
      my $key_a = /$re/ ? $order{$1} : 0;
      my $key_b = /$re/ ? $order{$1} : 0;
      $key_a <=> $key_b || $a cmp $b
   }
      @unsorted;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...