This is a range class written for PHP5. It's really just a collection of static functions that have been wrapped into a class. You could either use it like this or subclass it to make a real Range object.
A "range" consists of an array, and two indexes into the array, typically here called $first and $last. The elements of the range consist of $array[$first], $array[$first+1], ..., $array[$last-2], and $array[$last-1] inclusive.
Note that $array[$last] is not an element of the range. This makes much of the arithmetic of working with ranges simpler: e.g.,
To use an entire array for a range, $first=0, $last=count($array);
the methods use these values as defaults if not provided explicitly
Iterating of the elements of an array can be done with for($i=$first; $i<$last; $i++);
$last-$first is the length of the range;
...and so on.
The comments denote this property using usual conventions: [$first,$last) is the interval from (and including) $first up to (but not including) $last.
Many of the methods provided by the class model existing array functions, without using them. There are two principal reasons why they're written the way they are:
There is no elegant way to get an array function to work on only
part of an array - in effect, the range is forced to be [0,count($array)).
These methods will work on objects that implement the ArrayObject interface; the native array functions won't.
The idea of using ranges is that it allows you to manipulate sections of a single whacking huge array (or ArrayObject) in place, rather than having to copy a section out to an extra array, transforming it (thus requiring the additional memory to store the transformed array), and then copying it back into place. You can obviously have several ranges all acting as "windows" into a single master array.
All range methods that transform arrays do so by having the array passed by reference. No temporary arrays of range elements are created, manipulated, returned or destroyed.
And looking at them just now I remembered that I was going to make a note of how all the argument-checking is split from the actual code; the methods are hence able to call on each other without wasting a lot of time repeatedly checking things - like whether or not callbacks are callable - that have already been checked.
Now for the usual weedy examples:
include_once('range.php');
function show($a)
{
echo join('', $a), "\n\n";
}
function lt($a,$b){return strcmp($a,$b)<0;}
/* Convert a few characters to upper case */
$a1 = range('a','z');
range::transform($a1, $a1, 'strtoupper', 5, 10, 5);
show($a1);
/* Looking for adjacent duplicates */
$a1 = range('a','e');
$a1 = array_merge($a1, $a1, $a1, $a1, $a1);
show($a1);
$i = range::adjacent_find($a1);
if($i==count($a1))
echo "No adjacent duplicates.\n";
else
echo $a1[$i],' ',$a1[$i+1],"\n";
range::random_shuffle($a1);
show($a1);
$i = range::adjacent_find($a1);
if($i==count($a1))
echo "No adjacent duplicates.\n";
else
echo $a1[$i],' ',$a1[$i+1],"\n";
/* It's the English alphabet. You've seen it before. */
$a1 = range('a','z');
show($a1); // And you'll see it again
/* Backwards! */
range::reverse($a1);
show($a1);
/* Shuffled! */
range::random_shuffle($a1);
show($a1);
/* Sorted! */
range::stable_sort($a1,'lt');
show($a1);
/* Heaped! */
range::make_heap($a1,'lt');
show($a1);
/* Sorted again! */
range::sort_heap($a1,'lt');
show($a1);
/* And why _does_ A come before B? */
range::random_shuffle($a1);
show($a1);
/* The first and the last */
$max = range::max_element($a1,'lt');
$min = range::min_element($a1,'lt');
echo $a1[$min],' ',$a1[$max],"\n";
/*
* In this case, the $a2 array gets built by PHP on the fly, so we don't
* need to pre-book space for the results.
* The default values of $first and $last for an empty array are 0 and 0.
*/
$a2 = array();
range::transform($a1,$a2,'strtoupper',6,15);
show($a2);
/* Step forward to the next permutation of these letters: */
range::next_permutation($a2,'lt');
show($a2);
range::sort($a2,'lt');
show($a2);
/* And now step back again: */
range::prev_permutation($a2,'lt');
show($a2);
/* All of the permutations of "abcd" in alphabetical order.
$a2 = range('a','d');
for($i=0; $i<24; ++$i)
{
show($a2);
range::next_permutation($a2,'lt');
}