This 'snippet' is a little module on its own, containing just one sub: is_sorted(), to test if the parameter list is sorted according to some comparison rule, as the optional block for sort. Strictly speaking, I think this module is a bit small to put on CPAN.

The return value will be one of the following:

2
The list is strictly sorted according to the rules of the code block. Each next element is greater than the previous one.
1
The list is sorted according to the rules of the code block, but some consecutive elements are the same.
'0E0'
flat: all elements are the same.
0
The list is not sorted: sometimes it goes up, and sometimes down.
-1
The list is sorted opposite to the rules of the code block, with some consecutive elements the same.
-2
The list is strictly sorted opposite to the rules of the code block, where each next element is less than the previous one.

Use as:

use List::Util::IsSorted 'is_sorted'; print is_sorted { $a <=> $b } 1, 3, 5, 5, 8; # prints 1

I even provided the POD. :)

update I changed the code so it never returns undef. It'll now return true if the list is "sorted", even if that means "flat" (all items the same). Only truely unsorted lists will return false (0).

package List::Util::IsSorted; use strict; use base 'Exporter'; use vars qw(@EXPORT_OK); @EXPORT_OK = 'is_sorted'; sub import { # prevent "used only once" warning no strict 'refs'; my $caller = caller; local *{$caller."::a"} = local *{$caller."::b"} = \0; # business as usual goto &Exporter::import; } sub is_sorted (&@) { my $code = shift; my %dir; return '0E0' unless @_ > 1; no strict 'refs'; my $caller = caller; local(*{$caller."::a"}) = \my $a; local(*{$caller."::b"}) = \my $b; $a = shift; foreach (@_) { $b = $_; $dir{0 <=> &{$code}()}++; return 0 if $dir{1} && $dir{-1}; $a = $b; } my $dir = $dir{1} ? 1 : $dir{-1} ? -1 : '0E0'; $dir <<= 1 unless $dir{0}; return $dir || '0E0'; } 1; __END__ =head1 NAME List::Util::IsSorted - Test if a list is sorted, in the style of L<Lis +t::Util> =head1 SYNOPSIS use List::Util::IsSorted 'is_sorted'; $sort_status = is_sorted { $a cmp $b } qw(alpha beta gamma); =head1 DESCRIPTION C<List::Util::IsSorted> contains a subroutine to test if a list is sor +ted according to a comparison test. =over 4 =item is_sorted BLOCK LIST Tests to see if LIST is sorted strictly ascending or descending, not-descending or not-ascending, flat, or unsorted, by calling BLOCK multiple times, setting C<$a> and C<$b> to a pair of parameter values +each time. The return value is one of the following: =over 6 =item 2 strictly ascending: The list is sorted according to the rules of the c +ode block, where each next element compares as greater than the previous o +ne. =item 1 ascending: The list is sorted according to the rules of the code block +, though some consecutive elements compare as the same. =item '0E0' flat: the list contains only elements that compare as the same. =item '0' unsorted: the list contains changes in both ways =item -1 descending: The list is sorted I<opposite> to the rules of the code bl +ock, though some consecutive elements compare as the same. =item -2 strictly descending: The list is sorted opposite to the rules of the c +ode block, where each next element compares as less than the previous one. =back =back =head1 SEE ALSO L<List::Util> =back =cut

Replies are listed 'Best First'.
Re: List::Util::IsSorted
by ysth (Canon) on Apr 20, 2004 at 14:14 UTC
    You could consider contributing it to List::Utils (not List::Util, which is in the core and only will provide often-wanted stuff, but the other module which has a range of stuff considered too little useful for List::Util).