我在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
的顺序
答案 0 :(得分:6)
按给定集合排序(排序)的一种方法是将数字顺序与其元素相关联。
然后,我们需要在列表中的字符串中找到这些键进行排序。通过Schwartzian转换在实际排序之前完成一次。
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
通过正则表达式在字符串中查找键,从而使列表中的元素与排序键相关联。考虑到这一点,上述内容可以合理地普遍使用,并带有所需的键列表。
答案 1 :(得分:5)
对于简短列表,请使用可按顺序标识序列的排序功能
@sorted = sort {
($b =~ /sf$/) <=> ($a =~ /sf$/)
|| ($b =~ /ef$/) <=> ($a =~ /ef$/)
|| ($b =~ /vld$/) <=> ($a =~ /vld$/)
|| ($b =~ /val$/) <=> ($a =~ /val$/)
} @alist;
答案 2 :(得分:3)
如果在代码之前始终有_
,并且代码始终在结尾处
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;