MathCurvesSurfacesWallpaper GroupsGallerySoftwarePOV-Ray
ProgramingLinuxPerl PythonHTMLCSSJavaScriptPHPJavaEmacsUnicode ♥
Web Hosting by 1＆1

# Perl: General Function for Sorting Matrix

Xah Lee,

Here's a function that can sort a matrix in all possible ways.

the following Python version i wrote in 2006, but was incorrect.

```# -*- coding: utf-8 -*-
# python

# WARNING: THE CODE IS INCORRECT.

# sort_matrix( matrix, [[n1, s1, d1], [n2, s2, d2], [n3, s3, d3], …]) returns a sorted matrix by n1 th column, if tie, then by n2 th column … and so on.

# The first argument is a list, whose elements are lists of equal lengths.

# s1, s2, s3… are booleans. If True, then the corresponding column are interpreted as a string and the ordering is lexicographical.

# d1, d2, d3… are booleans. If True, the sort for the corresponding column are ascending.

# Example:.

# myMatrix =
#  [
#    [3, 99, 'a'],
#    [2, 77, 'a'],
#    [1, 77, 'a']
#  ];

# sort_matrix(myMatrix,[[3,True,True],[2,False,True]])

# This means sort by 3th column, regarding it as strings, and in ascending order. If tie, sort by 2th column, regarding it as number, in ascending order. It returns:

# [[2,77,'a'],
#  [1,77,'a'],
#  [3,99,'a']]

def sort_matrix(matrix, directives):
result=matrix
for dir in directives:
if dir[1]: # consider as string
if dir[2]: # ascending
result.sort(lambda x,y: cmp( str(x[dir[0]-1]), str(y[dir[0]-1])) )
else:      # descending
result.sort(lambda x,y: cmp( str(x[dir[0]-1]), str(y[dir[0]-1])), None, True)
else: # consider as number
if dir[2]: # ascending
result.sort(lambda x,y: cmp(float(x[dir[0]-1]), float(y[dir[0]-1])) )
else:      # decending
result.sort(lambda x,y: cmp(float(x[dir[0]-1]), float(y[dir[0]-1])), None, True )
return result```

## Perl

This Perl version i wrote in 1999, and was put in production use in a ecommerce server.

```# -*- coding: utf-8 -*-
# perl

=pod

sort_matrix( \$matrix, [[\$n1, \$stringQ, \$directionQ], [\$n2, \$stringQ,
\$directionQ], …]) sorts a matrix by \$n1 th column then \$n2 th…and
so on.

\$matrix must be a reference to references of arrays, having the form
[[\$e1, \$e2,…], […], …].  \$stringQ is a boolean indicating
whether to treat corresponding columns as a strings instead of as
number in the sorting process. True means string. \$directionQ is a
boolean indicating ascending sort or not for the corresponding
column. In the column spec \$n1 \$n2 …, index counting starts at 0.

Example:

my \$ref_matrix =
[
[3, 99, 'a'],
[2, 77, 'a'],
[1, 77, 'a']
];

sort_matrix( \$ref_matrix,  [ [2,1,1], [1,0,1] ]);
# this means sort by third column, regarding it as strings,
# and in ascending order. If tie, sort by second column,
# regarding it as number, in ascending order.

# returns [[2,77,'a'],[1,77,'a'],[3,99,'a']];

=cut

sub sort_matrix(\$\$) {
my \$ref_matrix = \$_[0];
my @indexMatrix = @{\$_[1]};

my @indexes = map {\$_->[0]} @indexMatrix;
my @operators = map {\$_->[1] ? ' cmp ' : ' <=> '} @indexMatrix;
my @directions = map {\$_->[2]} @indexMatrix;

my \$body_code = '';
my @body_array;
for (my \$i = 0; \$i <= \$#indexes; \$i++) {
if (\$directions[\$i]) {
push(@body_array, "(\\$a->[\$i]" . \$operators[\$i]  . "\\$b->[\$i])");
} else {
push(@body_array, "(\\$b->[\$i]" . \$operators[\$i]  . "\\$a->[\$i])");
};
};
\$body_code = join( ' or ', @body_array);

my \$array_code = '(map { [' . join(q(, ), map {"\\$_->[\$_]"} @indexes) . ', \$_]} @\$ref_matrix)';

my \$code = "map {\\$_->[-1]} (sort { \$body_code} \$array_code)";
my @result = eval \$code;
return [@result];
};
```