sort based on the own pattern

Hi Everyone,

[root@]# cat 1.pl
#!/usr/bin/perl
use strict;
use warnings;

my @test=("a","b","c","d");
print @test;

[root@]# ./1.pl
abcd

if i want to sort the @test, based on my own partten, the output is "cbda", how to do? as i know perl sort i can use cmp and <=>, but how to do with my own sort patten. :confused:

Thanks

The first thing you should define is what your pattern is. Otherwise, just pass a code block or sub-reference as the first argument to sort, remember that the left- and right-hand variables are always named $a and $b, and return one of -1,0,1 (<, =, >).

Hi pludi,

for "my @test=("a","b","c","d");", after print, it will be abcd, but my own pattern is "c" is the 1st, "b" is the 2nd, "d" is 3rd, and last "a".

if i just use "cmp" or "<=>", cannot achieve this customized sort pattern.

Thanks

What about d-z, A-Z, 0-9, ...? What about values with more than 1 character?

One possible approach, if it's only a few possible characters (=< 10), would be to translate them to numbers, do a numerical comparison, and translate them back after sorting, eg:

#!/usr/bin/perl
@test = qw/a b c d/;
print "@test\n";
@sorted = map { $_->[0] }
  sort { $a->[1] cmp $b->[1] }
  map { $a = $_; $a =~ tr/abcd/4213/; [ $_, $a ] } @test;
print "@sorted\n";
1 Like

"would be to translate them to numbers, do a numerical comparison,"

Thanks :b:

---------- Post updated at 07:00 AM ---------- Previous update was at 06:49 AM ----------

What about if @test = qw/aaa bb 44 BB9/, the output sequence is "BB9 bb aaa 44"? i tried using the code yours, but cannot achieve.

Thanks

The sort function uses code just like any regular sub. So if you can write the code to do single comparisons giving the right results, you can plug it into the sort function without problems.

If you're doing this to learn Perl, read the code I've given, plus perldoc -f sort and perldoc -f map, and then ask specific questions.

If you need a generic sorting mechanism, give us more details on the required order, covering every possible valid input.

hi pludi,

i tried on sort and map, tried to want to replace each element with number, but failed. I used one way which is very unefficient to do it.

[root@P1Portal ]# cat 1.pl
#!/usr/bin/perl
use strict;
use warnings;

my @test = qw/aaa bb 44 BB9/;
my @new;
foreach (@test) {
        if ($_ =~ m/^(BB9)/i ) {
                $new[0] = $_;
        } elsif ($_ =~ m/^(bb)/i ) {
                $new[1] = $_;
        } elsif ($_ =~ m/^(aaa)/i ) {
                $new[2] = $_;
        } elsif ($_ =~ m/^(44)/i ) {
                $new[3] = $_;
        }
}
print @new;

exit;
#my @sorted = map { $_->[0] } sort { $a->[1] cmp $b->[1] } map { $a = $_; $a = splice(@test,0,4,'4','3','2','1'); [ $_, $a ] } @test;
#print "@sorted\n";

[root@P1Portal ]# ./1.pl
BB9bbaaa44

:mad:

Well, that sort order seems pretty much arbitrary. Unless you can come up with a concise description of the algorithm you won't get any better results than what you already have.