The function
Here some examples.@list = qw(); separate definition of @list, which gives a bit longer code sort ( @list ); sort ( { ... } @list );with block {...} before the list/array; the block can also contain subroutines sort ( custom_function @list );
# ASCIIbetical order or ASCII#Character order @list = qw( 0 1 2 3 5 8 13 21 34 55 89 144 233 377 610 ); @list_sorted = sort( @list ); print("@list_sorted\n");# Output: 0 1 13 144 2 21 233 3 34 377 5 55 610 8 89
# this is probably what you want, thanks to the operator <=> and the global variables $a and $b @list = qw/0 1 2 3 5 8 13 21 34 55 89 144 233 377 610/; @list_sorted = sort( { $a <=> $b } @list ); print("@list_sorted\n");# Output: 0 1 2 3 5 8 13 21 34 55 89 144 233 377 610
# descending order: $b <=> $a @list = qw/0 1 2 3 5 8 13 21 34 55 89 144 233 377 610/; @list_sorted = sort( { $b <=> $a } @list ); print("@list_sorted\n");# Output: 610 377 233 144 89 55 34 21 13 8 5 3 2 1 0
# ASCIIbetical order or ASCII#Character order @list = qw(c Z b Y a X); @list_sorted = sort( @list ); print("@list_sorted\n");# Output: X Y Z a b c
# probably what you want, thanks to the operator cmp and the global variables $a and $b # the lc function (lowercase) is necessary to compare all characters @list = qw(c Z b Y a X); @list_sorted = sort( { lc($a) cmp lc($b) } @list ); print("@list_sorted\n");# Output: a b c X Y Z
# here a combination with function substr: the last digit of a number determines the sort order @list = qw(8 2 24 16 2345 6 1 64 133); @list_sorted = sort( { substr($a,-1,1) <=> substr($b,-1,1) } @list ); print("@list_sorted\n");# Output: 1 2 133 24 64 2345 16 6 8
# here a combination with function length: the length determines the sort order # in case the strings have the equal length, then the ASCIIbetical order determines the sort order @list = qw(like Cappuccino YOU do Zen); @list_sorted = sort( { length($a) <=> length($b) } @list ); print("@list_sorted\n");# Output: do YOU Zen like Cappuccino
# here the previous code again, but now in a custom subroutine mc_compare # notice that this subroutine handles the global variables $a and $b and does not have any arguments @list = qw(like Cappuccino YOU do Zen); sub mc_compare { length($a) <=> length($b) } @list_sorted = sort( mc_compare @list ); print("@list_sorted\n");# Output: do YOU Zen like Cappuccino
# here an array of hashes, sorted on the numerical value 'age', hence <=> @name_age = ( {name => Daniel, age => 39}, {name => Sebastian, age => 41}, {name => Florence, age => 37} ); @name_age_sorted = sort( { $a->{age} <=> $b->{age} } @name_age ); foreach (@name_age_sorted) { print($_->{name}, " ", $_->{age} , "\n"); }Florence 37 Daniel 39 Sebastian 41
Notice that the previous array of hashes examples can be writen easier with the __DATA__ construction!# here an array of hashes, sorted on the string value 'name', hence cmp @name_age = ( {name => Daniel, age => 39}, {name => Sebastian, age => 41}, {name => Florence, age => 37} ); @name_age_sorted = sort { $a->{name} cmp $b->{name} } @name_age; foreach (@name_age_sorted) { print($_->{name}, " ", $_->{age}, "\n"); }Daniel 39 Florence 37 Sebastian 41
# here a combination with the split subroutine use Text::Trim;# Read and store data from __DATA__ section into an array @data = <DATA>; chomp(@data);# Sort the array based on the second numerical column, hence <=> @sorted_data = sort { (split /\s+/, $a)[1] <=> (split /\s+/, $b)[1] } @data;# print the sorted data # the foreach loop and the trim subroutine for a better output foreach (trim(@sorted_data)) { print($_ . "\n") if ($_); } __DATA__ apple 5 banana 2 orange 8 grape 1
Output: grape 1 banana 2 apple 5 orange 8
# here a combination with split in a own subroutine # if two numerial values are equal, one want to order by the names; that is what the logical operator || does use Text::Trim; @data = <DATA>; chomp(@data);# create your own function sub mc_compare { @a_value = (split /;/, $a); @b_value = (split /;/, $b); $a_value[1] <=> $b_value[1] || $a_value[0] cmp $b_value[0]; }# notice that this subroutine handles the global variables $a and $b and does not have any arguments here @sorted_data = sort(mc_compare @data); foreach ( trim(@sorted_data) ) { print($_ . "\n") if ($_); } __DATA__ apple;5 grape;2 orange;8 banana;2
NowOutput: banana;2 grape;2 apple;5 orange;8
Let's break the code# list of strings @strings = ("apple", "banana", "orange", "grape", "kiwi");# Schwartzian Transform @sorted_strings = map { $_->[0] }# undecorate sort { $a->[1] <=> $b->[1] }# sort map { [$_, length($_)] } @strings;# decorate # print the sorted list print join(", ", @sorted_strings), "\n";# output: kiwi, apple, grape, banana, orange
Study the next example where the array of arrays (use Text::Trim; @data = <DATA>; chomp(@data); sub mc_compare { $a->[1] <=> $b->[1] || $a->[0] cmp $b->[0]; } # Schwartzian Transform @sorted_data = map { $_->[0] } sort mc_compare map { /;(\d+)/; [ $_, $1 ] } @data;# alternative: map { [ $_, substr($_,-1) ] } @data; foreach (trim(@sorted_data)) { print($_ . "\n") if ($_); } __DATA__ apple;5 grape;2 orange;8 banana;2
use Text::Trim; @data = <DATA>; chomp(@data); # Schwartzian Transform with multiple values using substr @sorted_strings = map { $_->[0] } sort { $a->[2] <=> $b->[2] or $a->[1] <=> $b->[1] } map { [$_, substr($_, 0, 5), substr($_, -3)] } @data;# print the sorted list foreach (trim(@sorted_strings)) { print($_ . " ") if ($_);# output: apple123 grape123 kiwi345 banana456 orange789 } __DATA__ apple123 banana456 orange789 grape123 kiwi345