I have a list in Perl.
@alist=("a_vld","a_sf","a_ef","a_val");
print join(',', @alist), "\n";
Run Code Online (Sandbox Code Playgroud)
Output:
a_vld,a_sf,a_ef,a_val
Run Code Online (Sandbox Code Playgroud)
How can I re-order the elements in list such that its output is as following expected output:
a_sf,a_ef,a_vld,a_val
Run Code Online (Sandbox Code Playgroud)
Note: a_ will keep changing with different strings but I want to preserve the order of sf,ef,vld,val
One way to order (sort) by a given set is to associate a numeric order with its elements.
Then we need to find these keys in the strings in the list to sort. That is done once, ahead of the actual sorting, via the Schwartzian transform.
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";
Run Code Online (Sandbox Code Playgroud)
This prints the line: a_sf a_ef a_vld a_val
The elements of the list are associated with the sorting keys by finding the key in the string via a regex. With this in mind the above can be used reasonably generally, with a desired list of keys .
For a short list, use a sort function that identifies the sequences in order
@sorted = sort {
($b =~ /sf$/) <=> ($a =~ /sf$/)
|| ($b =~ /ef$/) <=> ($a =~ /ef$/)
|| ($b =~ /vld$/) <=> ($a =~ /vld$/)
|| ($b =~ /val$/) <=> ($a =~ /val$/)
} @alist;
Run Code Online (Sandbox Code Playgroud)