foreach(range()) whilst efficiant in other languages, such as python, it is not (compared to a for) in php*.
php is a C-inspired language and thus for is entirely in-keeping with the lanuage aethetic to use it
<?php
//efficiant
for($i = $start; $i < $end; $i+=$step)
{
//do something with array
}
//inefficiant
foreach(range($start, $end, $step) as $i)
{
//do something with array
}
?>
That the officiant documentation doesnt mention the for loop is strange.
Note however, that in PHP5 foreach is faster than for when iterating without incrementing a variable.
* My tests using microtime and 100 000 iterations consistently (~10 times) show that for is 4x faster than foreach(range()).
range
(PHP 4, PHP 5)
range — Erstellt ein Array mit einem Bereich von Elementen
Beschreibung
range() gibt ein Array mit Elementen im Bereich von low bis high zurück. Wenn low > high, wird die Sequenz von high nach low sein.
Hinweis: Neuer Parameter
Der optionale Parameter step wurde in 5.0.0 eingeführt.
Ist ein step Wert angegeben, wird es Schrittweite zwischen den Elementen in der Sequenz verwendet. step sollte als positive Zahl angegeben werden. Ist step nicht angegeben, wird automatisch der Wert 1 angenommen.
Beispiel #1 range()
<?php
// array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
foreach(range(0, 12) as $number) {
echo $number;
}
// Der Parameter step wurde in PHP 5.0.0 eingeführt
// array(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
foreach(range(0, 100, 10) as $number) {
echo $number;
}
// Die Verwendung von Zeichenfolgen wurde in 4.1.0 eingeführt
// array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i');
foreach(range('a', 'i') as $letter) {
echo $letter;
}
// array('c','b','a');
foreach(range('c', 'a') as $letter) {
echo $letter;
}
?>
Hinweis: Vor der Version 4.1.0 hat die Funktion range() nur aufsteigende Integer Arrays erstellt. Die Unterstützung für Zeichenfolgen und Arrays in absteigender Reihenfolge wurde in 4.1.0 hinzugefügt. Werte mit Zeichenfolgen sind auf eine Länge von 1 limitiert. Wird eine Länge größer als 1 eingegeben, wird nur das erste Zeichen verwendet.
In den PHP Versionen 4.1.0 bis 4.3.2 werden numerische Zeichenfolgen von range() als Strings, und nicht als integer gesehen. Stattdessen werden diese für Zeichenfolgen genutzt, z.B. wird "4242" als "4" betrachtet.
Siehe auch shuffle(), array_fill() und foreach.
range
26-Aug-2008 02:11
27-Mar-2008 07:33
Here is a home rolled range() function that uses the step feature for those unfortunate souls who cannot use PHP5:
<?php
function my_range( $start, $end, $step = 1) {
$range = array();
foreach (range( $start, $end ) as $index) {
if (! (($index - $start) % $step) ) {
$range[] = $index;
}
}
return $range;
}
?>
10-May-2007 01:47
Quick HTML menus with minimum and maximum sets of years:
<?php
/*
** Quick HTML menus with minimum and maximum sets of years.
** @author Chris Charlton <chris@laflash.org>
** @license FREE!
*/
// Years range setup
$year_built_min = 1900;
$year_built_max = date("Y");
?>
<select id="yearBuiltMin" size="1">
<?php // Generate minimum years
foreach (range($year_built_min, $year_built_max) as $year) { ?>
<option value="<?php echo($year); ?>"><?php echo($year); ?></option>
<?php } ?>
</select>
<select id="yearBuiltMax" size="1">
<?php // Generate max years
foreach (range($year_built_max, $year_built_min) as $year) { ?>
<option value="<?php echo($year); ?>"><?php echo($year); ?></option>
<?php } ?>
</select>
02-Mar-2007 02:46
Here's how i use it to check if array is associative or not:
<?php
if (array_keys($arr)===range(0, sizeof($arr)-1)) {
// not associative array
} else {
// associative array
}
?>
07-Nov-2006 02:25
<?php
function srange ($s) {
preg_match_all("/([0-9]{1,2})-?([0-9]{0,2}) ?,?;?/", $s, $a);
$n = array ();
foreach ($a[1] as $k => $v) {
$n = array_merge ($n, range ($v, (empty($a[2][$k])?$v:$a[2][$k])));
}
return ($n);
}
$s = '1-4 6-7 9-10';
print_r(srange($s));
?>
Return:
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 6
[5] => 7
[6] => 9
[7] => 10
)
08-Jan-2006 03:36
A much simpler way of creating a range of even numbers is by starting with an even number:
<?php
range(2, 10, 2);
?>
21-Aug-2005 04:53
since its not stated explicitly above, thought id point out that you arent limited to using integers.
however, be careful when doing so, as you might not get the range you expect!
to illustrate:
<?php
$am = range(500,1600,10);
$fm = range(88.1,107.9,.2);
print_r($am);
print_r($fm);
?>
print_r($am) yields the expected result:
Array
(
[0] => 500
[1] => 510
[2] => 520
...
[109] => 1590
[110] => 1600
)
print_r($fm), however, falls a bit (1%) short:
Array
(
[0] => 88.1
[1] => 88.3
[2] => 88.5
...
[97] => 107.5
[98] => 107.7
)
so, if you want to use a non-integral step size params for numeric ranges, be sure to account for fp representation accuracy and error accumulation; a step size of something like pi or 1/10 could spell disaster for a large range. if in doubt, use integral steps and divide ... something like <?php range(88.1,108,.2) ?> might work to recover 107.9, but would not be scalable like, say <?php array_map(create_function('$x','return $x/10;'),range(881,1079,2)) ?>.
-emory
08-May-2005 03:13
This should emulate range() a little better.
<?php
function range_wroar($low, $high, $step = 1) {
$arr = array();
$step = (abs($step)>0)?abs($step):1;
$sign = ($low<=$high)?1:-1;
if(is_numeric($low) && is_numeric($high)) {
//numeric sequence
for ($i = (float)$low; $i*$sign <= $high*$sign; $i += $step*$sign)
$arr[] = $i;
} else {
//character sequence
if (is_numeric($low))
return $this->range($low, 0, $step);
if (is_numeric($high))
return $this->range(0, $high, $step);
$low = ord($low);
$high = ord($high);
for ($i = $low; $i*$sign <= $high*$sign; $i += $step*$sign) {
$arr[] = chr($i);
}
}
return $arr;
}
?>
23-Sep-2004 01:23
i figured i'd add some more functionality to the myRange() functions below.
now you can, besides giving a $step parameter,
1. count backwards
2. count with letters
3. give whatever parameter you want, there's nothing (i know of) that will cause an endless loop (try a negative $step for the previous function....)
<?php
function myRange($num1, $num2, $step=1)
{
if (is_numeric($num1) && is_numeric($num2))
{
//we have a numeric range
$step = ( abs($step)>0 ? abs($step) : 1 ); //make $step positive
$dir = ($num1<=$num2 ? 1 : -1); //get the direction
for($i = (float)$num1; $i*$dir <= $num2*$dir; $i += $step*$dir)
{
$temp[] = $i;
}
}
else
{
//we have a character range
$num1=ord((string)$num1); //convert to ascii value
$num2=ord((string)$num2);
$step = ( abs($step)>0 ? abs($step) : 1 ); //make $step positive
$dir = ($num1<=$num2 ? 1 : -1); //get direction
for($i = $num1; $i*$dir <= $num2*$dir; $i += $step*$dir)
{
$temp[] = chr($i);
}
}
return $temp;
}
print_r(myRange( 1, 3, 0.5 )); //you can use fractional steps
print_r(myRange( "a", "k", 3 )); //or count letters
print_r(myRange( "5", "9" )); //numbers are detected even if hidden in strtings
print_r(myRange( "!", "%", 1/pi() )); //or mess around with senseless parameters
?>
01-Sep-2004 06:38
To speed your MyRange() function, I have created a much nicer function with less code to sift through to include the step parameter.
<?php
// range() limitation for PHP <5.0.0
function myRange($num1, $num2, $step=1)
{
for($i = $num1; $i <= $num2; $i += $step)
{
$temp[] = $i;
}
return $temp;
}
?>
For whatever reason my comment was deleted..?
18-May-2004 04:57
Since users of < PHP 5.0.0 don't have the option of the step parameter, I've created a little function to account for it:
@USAGE: (int low, int high [, int step])
function myRange($low,$high,$step=1)
{
$ranArray = range($low,$high);
$step--;
$keys = count($ranArray);
for($i=0;$i<$keys;$i++)
{
$retArray[] = $ranArray[$i];
$i = $i + $step;
}
return $retArray;
}
// Example usage:
print_r(myRange(1,11,2));
// Returns the array:
// [0] => 1
// [1] => 3
// [2] => 5
// [3] => 7
// [4] => 9
// [5] => 11
