PHPのお勉強!

PHP TOP

range

(PHP 4, PHP 5, PHP 7, PHP 8)

rangeある範囲の要素を含む配列を作成する

説明

range(string|int|float $start, string|int|float $end, int|float $step = 1): array

ある範囲の要素を含む配列を作成します。

startend が両方文字列で、かつ step が整数の場合、 生成される配列はバイト列のシーケンスになります。 そうでない場合、生成される配列は数値のシーケンスになります。

startend よりも小さい場合、シーケンスは増加します。 そうでない場合、シーケンスは減少します。

パラメータ

start

シーケンスの最初の値。

end

シーケンスの最後としてあり得る値。

step

step は、生成されるシーケンスの個別の値が どれくらい離れているかを指定します。

シーケンスが減少する場合、step は負の値を指定しても構いません。

step が 端数のない float の場合、整数として解釈されます。

戻り値

要素のシーケンスを配列として返します。 最初の要素は start になり、 end になるまで続きます。 シーケンスのそれぞれの値は、step だけ離れています。

返される配列の最後の要素は、 end または シーケンスの直前の要素になります。 どちらになるかは、step の値によります。

startend が両方文字列で、かつ step が整数の場合、 生成される配列は、バイト列のシーケンスになります。 一般的にはラテン文字の ASCII 文字からなるシーケンスです。

start, end, step のうち少なくともひとつが float の場合、 生成される配列は float のシーケンスになります。

その他の場合、生成される配列は整数のシーケンスになります。

エラー / 例外

  • step0 の場合、ValueError がスローされます。
  • start, end, step が有限の値(is_finite()) でない場合、 ValueError がスローされます。
  • step が負の値なのに、生成される範囲が増えている(つまり、 $start <= $end) 場合、 ValueError がスローされます。
  • start または end が空文字列 '' の場合、E_WARNING が発生し、空文字列は 0 として解釈されます。
  • start または end数値形式の文字列 でない、長さが1バイトより大きい値の場合、E_WARNING が発生します。
  • start または end が 暗黙のうちに整数にキャストされた文字列の場合、 E_WARNING が発生します。なぜなら、他の境界の入力値は数値だからです。
  • stepfloat の場合、 かつ startend数値形式の文字列 でない場合、E_WARNING が発生します。

変更履歴

バージョン 説明
8.3.0 startend が両方文字列の場合、range() は常にバイト列を要素とした配列を生成するようになりました。 これより前のバージョンでは、境界の値のうちのひとつが数値形式の文字列の場合に、もう一方の境界の値を整数にキャストしていました。
8.3.0 start または end が 暗黙のうちに整数にキャストされた文字列の場合、 E_WARNING が発生するようになりました。 なぜなら、他の境界の入力値が数値だからです。
8.3.0 start または end が数値形式の文字列でなく、かつ長さが1バイトより大きい値の場合、 E_WARNING が発生するようになりました。
8.3.0 start または end が空文字列の場合、E_WARNING が発生するようになりました。
8.3.0 step が 端数のない float の場合、整数として解釈されるようになりました。
8.3.0 step が負の値なのに、生成される範囲が増えている場合、 ValueError がスローされるようになりました。
8.3.0 step が有限の値でない場合、 ValueError がスローされるようになりました。
8.3.0 start または end が配列、objectresource の場合、 TypeError がスローされるようになりました。 これより前のバージョンでは、これらの値は暗黙のうちに整数にキャストされていました。

例1 range() の例

<?php
echo implode(', ', range(0, 12)), PHP_EOL;

echo
implode(', ', range(0, 100, 10)), PHP_EOL;

echo
implode(', ', range('a', 'i')), PHP_EOL;

echo
implode(', ', range('c', 'a')), PHP_EOL;

echo
implode(', ', range('A', 'z')), PHP_EOL;
?>

上の例の出力は以下となります。

0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100
a, b, c, d, e, f, g, h, i
c, b, a
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, [, \, ], ^, _, `, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z

参考

add a note

User Contributed Notes 30 notes

up
132
Palz
12 years ago
To create a range array like

Array
(
[11] => 1
[12] => 2
[13] => 3
[14] => 4
)

combine two range arrays using array_combine:

array_combine(range(11,14),range(1,4))
up
16
gtisza at gmail dot com
11 years ago
You might expect range($n, $n-1) to be an empty array (as in e.g. Python) but actually PHP will assume a step of -1 if start is larger than end.
up
13
php at keith tyler dot com
10 years ago
So with the introduction of single-character ranges to the range() function, the internal function tries to be "smart", and (I am inferring from behavior here) apparently checks the type of the incoming values. If one is numeric, including numeric string, then the other is treated as numeric; if it is a non-numeric string, it is treated as zero.

But.

If you pass in a numeric string in such a way that is is forced to be recognized as type string and not type numeric, range() will function quite differently.

Compare:

<?php
echo implode("",range(9,"Q"));
// prints 9876543210

echo implode("",range("9 ","Q")); //space after the 9
// prints 9:;<=>?@ABCDEFGHIJKLMNOPQ

echo implode("",range("q","9 "));
// prints qponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:987654
?>

I wouldn't call this a bug, because IMO it is even more useful than the stock usage of the function.
up
9
Alien426
9 years ago
The function will generate an array of integers even if your numerical parameters are enclosed in quotes.
<?php
var_dump
( range('1', '2') ); // outputs array(2) { [0]=> int(1) [1]=> int(2) }
?>

An easy way to get an array of strings is to map strval() to the range:
<?php
var_dump
( array_map('strval', range('1', '2')) ); // outputs array(2) { [0]=> string(1) "1" [1]=> string(1) "2" }
?>
up
5
ccb_bc at hotmail dot com
5 years ago
<?php
function natural_prime_numbers(array $range, bool $print_info = false) : array {
$start_time = time();
$primes_numbers = array();
$print = '';
$count_range = count($range);
foreach(
$range as $number){
$values_division_number = array();
if(
$number === 0 || $number === 1 || !is_int($number)){ // eliminate 0, 1 and other no integer
continue;
}
if(
$number != 2 && $number%2 === 0){ // eliminate 2 and pairs numbers
continue;
}
for(
$i = 1; $i <= $number; $i++){
$resultado_divisao = $number / $i;
$values_division_number[$i] = $resultado_divisao;

if(
$count_range <= 20){ // $count_range <= 20 (+ performance)
$print .= PHP_EOL;
$info = 'The number '.$number.' divided by the number '.$i.' is equal to: '.($number / $i);
$print .= $info;
if(
$i === $number){
$print .= PHP_EOL;
}
}

array_walk($values_division_number, function($value, $index) use (&$values_division_number, &$number){ // reference change values
// eliminate floats and others numbers not are equal 1 and own number
if(is_float($value) && $value != $number && $value > 1){
unset(
$values_division_number[$index]);
}
});

$values_division_number = array_values($values_division_number); // reindex array

// here we want only array with 2 indexes with the values 1 and own number (rule to a natural prime number)
if(count($values_division_number) === 2 && $values_division_number[0] === $number && $values_division_number[1] === 1){
$primes_numbers[$number] = $number;
}

}
}
return array(
'length_prime_numbers' => count($primes_numbers),
'prime_numbers' => array_values($primes_numbers),
'print' => $print,
'total_time_processing' => (time() - $start_time).' seconds.',
);
}
var_dump(natural_prime_numbers(range(0, 11))); // here the range() function ;-)

// Result:
// array (size=3)
// 'length_prime_numbers' => int 5
// 'prime_numbers' =>
// array (size=5)
// 0 => int 2
// 1 => int 3
// 2 => int 5
// 3 => int 7
// 4 => int 11
// 'print' => string '
// O número 2 dividido pelo número 1 é igual a: 2
// O número 2 dividido pelo número 2 é igual a: 1

// O número 3 dividido pelo número 1 é igual a: 3
// O número 3 dividido pelo número 2 é igual a: 1.5
// O número 3 dividido pelo número 3 é igual a: 1

// O número 5 dividido pelo número 1 é igual a: 5
// O número 5 dividido pelo número 2 é igual a: 2.5
// O número 5 dividido pelo número 3 é igual a: 1.6666666666667
// O número 5 dividido pelo número 4 é igual a: 1.25
// O número 5 dividido pelo '...

// **************************** //
//
// * Remember that the function is recursive, that is: a range of 5000 takes more than 1 minute on a processor Intel® Core™ i5-8250U (3.40 GHz).
//
// **************************** //
?>
up
8
luca.favorido ATgmailDOT com
8 years ago
The function "range" is very useful to get an array of characters as range('C','R') does.

At work, I had to extend the function range($a,$b) to work in this special case: with two uppercase strings $a and $b, it should return all the possible strings between $a and $b.
This could be used for example to get the excel column indexes.
e.g. <?php range('A','AD') ==> array('A','B','C',...,'Z','AA','AB','AC','AD') ?>

So I wrote the function getrange($min,$max) that exactly does this.

<?php

function getcolumnrange($min,$max){
$pointer=strtoupper($min);
$output=array();
while(
positionalcomparison($pointer,strtoupper($max))<=0){
array_push($output,$pointer);
$pointer++;
}
return
$output;
}

function
positionalcomparison($a,$b){
$a1=stringtointvalue($a); $b1=stringtointvalue($b);
if(
$a1>$b1)return 1;
else if(
$a1<$b1)return -1;
else return
0;
}

/*
* e.g. A=1 - B=2 - Z=26 - AA=27 - CZ=104 - DA=105 - ZZ=702 - AAA=703
*/
function stringtointvalue($str){
$amount=0;
$strarra=array_reverse(str_split($str));

for(
$i=0;$i<strlen($str);$i++){
$amount+=(ord($strarra[$i])-64)*pow(26,$i);
}
return
$amount;
}
?>
up
17
ThinkMedical at Gmail dot com
16 years ago
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()).
up
4
jazzduck AT gmail DOT com
10 years ago
Despite the line above that says that the $step value should be "given as a positive number," the range() function will in fact correctly handle reversed (decrementing) ranges. For example:

<?php print_r( range( 24, 20 ) ); ?>
Array
(
[0] => 24
[1] => 23
[2] => 22
[3] => 21
[4] => 20
)

<?php print_r( range( 20, 11, -3 ) ); ?>
Array
(
[0] => 20
[1] => 17
[2] => 14
[3] => 11
)

It will actually ignore the sign of the $step argument, and determine whether to increment or decrement based purely on whether $start > $end or $end > $start. For example:

<?php print_r( range( 20, 11, 3 ) ); ?>
Array
(
[0] => 20
[1] => 17
[2] => 14
[3] => 11
)

<?php print_r( range( 11, 20, -3 ) ); ?>
Array
(
[0] => 11
[1] => 14
[2] => 17
[3] => 20
)