【转】鲜为人知的 PHP range() 函数

PHP中有哪些冷门但很实用的函数?

作为一个 PHPer ,如果想要你生成 [1,31] 区间的 31 个数字,你一般会怎么做?

仔细想想,好好回忆一下,你第一时间想到的,会不会是使用一个 for 循环来生成,就像下面这样

1
2
3
4
5
$days = array();

for($i = 1; $i <= 31; $i++ ) {
$days[] = $i;
}

我想,应该,很少人会使用 range() 函数来生成$days = range(1,31,1);

我不知道这是不是我们 PHPer 的悲剧,因为,似乎,很少有教程会交代可以使用 foreach(range()) 的方式来代替 for 循环。

其实,PHP 中的 range() 函数比 Python 中的 range() 强大多了,除了没有使用生成器的方式。

range() 函数

根据官方文档,range() 函数被归纳为 「 数组函数 」,因为它的结果就是产生一个数组,一个普通数组。

range() 函数的原型如下

array range ( mixed $start , mixed $end [, number $step = 1 ] )
range() 函数根据范围 [$start,$end] 创建一个数组,步长为 $step ,默认步长为 1

注意: 返回的区间是一个左闭右闭的区间,也就是包含了 $start 和 $end 两个值。

参数 说明
start 返回的数组区间序列的第一个值
end 返回的数组区间序列结束于 end 的值
step 如果设置了步长 step,会被作为单元之间的步进值。step 应该为 正值。不设置 step 则默认为 1。

用法一 : $start 和 $end 参数都是整数

  1. 返回整数区间 [0,12] 且步长为 1 的数组

    1
    2
    3
    4
    // array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
    foreach (range(0, 12) as $number) {
    echo $number;
    }
  2. 返回整数区间 [0,100] 且步长为 10 的数组

    1
    2
    3
    4
    // array(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
    foreach (range(0, 100, 10) as $number) {
    echo $number;
    }
  3. 返回整数区间 [0,99] 且步长为 10 的数组

    1
    2
    3
    4
    // array(0, 10, 20, 30, 40, 50, 60, 70, 80, 90)
    foreach (range(0, 99, 10) as $number) {
    echo $number, " " ;
    }

注意:返回的数组的最后一个值为 90 ,因为 100 < 99 ,所以不满足条件

  1. 如果步长为负数,那么会取该步长的绝对值

    1
    2
    3
    4
    // array(0, 2, 4, 6, 8, 10, 12)
    foreach (range(0, 122) as $number) {
    echo $number;
    }
  2. 如果 $start < $end,那么返回的数组会从大到小

    1
    2
    3
    4
    // array(12, 10, 8, 6, 4, 2, 0)
    foreach (range(12, 02) as $number) {
    echo $number;
    }
  3. 如果步长 $step 为 0 ,会抛出一个异常

    1
    2
    // Warning: range(): step exceeds the specified range
    var_dump(range(12, 0, 0));
  4. 如果步长为字符串,那么会使用 intval() 转换为整数,如果转换后的结果为 0,则参考 6

    1
    2
    3
    4
    // array(12, 10, 8, 6, 4, 2, 0)
    foreach (range(12, 0'2a') as $number) {
    echo $number;
    }

用法二 : $start$end 参数可以是整数也可以是浮点数,$step 也可以是浮点数

  1. $start$end 是浮点数,而 $step 是整数,结果和整数是类似的

    1
    2
    3
    4
    // array(12.8, 10.8, 8.8, 6.8, 4.8, 2.8)
    foreach (range(12.8, 2.22) as $number) {
    echo $number;
    }
  2. $start$end 是浮点数,且 $step 也是浮点数,结果和整数也是类似的

    1
    2
    3
    4
    // array(12.8, 10.3, 7.8, 5.3, 2.8)
    foreach (range(12.8, 2.22.5) as $number) {
    echo $number;
    }
  3. 如果步长为字符串,那么会使用 doubleval() 转换为浮点数,如果步长为 0.0 那么将抛出异常

    1
    2
    3
    4
    // array(12.8, 10.3, 7.8, 5.3, 2.8)
    foreach (range(12.8, 2.2'2.5') as $number) {
    echo $number;
    }

转换后步长为 0 则抛出异常

1
2
3
4
// Warning: range(): step exceeds the specified range
foreach (range(12.8, 2.2'a2.5') as $number) {
echo $number;
}

用法三 : $start$end 如果有一个是整数或者浮点数

$start$end 如果有一个是整数或者浮点数,而另一个是字符串,那么会将另一个也转换为整数或者浮点数

  1. 一个是整数而另一个是字符串整数,那么会将另一个转换为整数,结果和都是整数是类似的

    1
    2
    3
    4
    // array(0, 2, 4, 6, 8, 10, 12)
    foreach (range(0, '12'2) as $number) {
    echo $number;
    }
  2. 一个是浮点数而另一个是字符串整数或浮点数,那么会将另一个转换为浮点数,结果和都是整数是类似的

1
2
3
4
// array(12.8, 10.8, 8.8, 6.8, 4.8, 2.8)
foreach (range(12.8, '2', 2) as $number) {
echo $number;
}

用法四 : $start$end 如果全部是字符串

$start$end 如果全部是字符串,那么会取两个字符串的第一个字母,并按照 ASCII 字母顺序表,取步长对应的值

  1. 如果 $start$end 都是单个字母,那么直接按照 ASCII 顺序取步长的值

    1
    2
    3
    4
    // array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i');
    foreach (range('a', 'i') as $letter) {
    echo $letter;
    }
  2. 如果按照 ASCII 顺序,$start 大于 $end ,那么会反向步长取值,这个和整数是类似的

    1
    2
    3
    4
    // array('c', 'b', 'a');
    foreach (range('c', 'a') as $letter) {
    echo $letter;
    }
  3. 如果 $start$end 任意一个字符串长度大于 1 ,那么只会取第一个字母

    1
    2
    3
    4
    // array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i');
    foreach (range('abc', 'i') as $letter) {
    echo $letter;
    }
  4. 如果两个都是字符串,而其中一个是整数字符串或者浮点数字符串,那也会当作普通字符串来处理

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

那么,我们如何使用range()来输出 ASCII 的所有可见字符呢?

1
2
<?php
echo json_encode(range(' ', '~'));

输出是

1
[" ","!","\"","#","$","%","&","'","(",")","*","+",",","-",".","\/","0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?","@","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","{","|","}","~"]

原文地址

https://www.twle.cn/c/yufei/phpmiss/phpmiss-basic-range.html

因为热爱,所以执着。