作为一门 Web 开发语言,PHP 无疑是成功的:
- 只需简单的学习便可快速上手
- 内置大量系统函数
- 动态解释型更快更灵活的应对业务快速迭代
- ……
PHP 的数组函数非常丰富,用好这些系统内置函数,让你的开发效率事半功倍。
1. array_column
1.1 提取指定列
相信很多 PHPer 对这个函数并不陌生,这个函数就是取数组中的某一列,如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| $records = array( array( 'id' => 2135, 'first_name' => 'John', 'last_name' => 'Doe', ), array( 'id' => 3245, 'first_name' => 'Sally', 'last_name' => 'Smith', ), array( 'id' => 5342, 'first_name' => 'Jane', 'last_name' => 'Jones', ), array( 'id' => 5623, 'first_name' => 'Peter', 'last_name' => 'Doe', ) );
$first_names = array_column($records, 'first_name'); print_r($first_names);
|
结果为
1 2 3 4 5 6 7
| Array ( [0] => John [1] => Sally [2] => Jane [3] => Peter )
|
1.2 指定列作键值对
如果我们需要提取last_name
,并用相应的id
作为键值,应该怎么实现呢?你可能想到了foreach
循环,但用array_column()
可以一行代码搞定:
1 2
| $last_names = array_column($records, 'last_name', 'id'); print_r($last_names);
|
输出结果:
1 2 3 4 5 6 7
| Array ( [2135] => Doe [3245] => Smith [5342] => Jones [5623] => Doe )
|
1.3 重新生成索引关系
我们还可以将每个用户的 ID 作为$records
的key
重新生成索引数组
1 2
| $idRecords = array_column($records, null, 'id'); print_r($idRecords);
|
结果为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| Array ( [2135] => Array ( [id] => 2135 [first_name] => John [last_name] => Doe )
[3245] => Array ( [id] => 3245 [first_name] => Sally [last_name] => Smith )
[5342] => Array ( [id] => 5342 [first_name] => Jane [last_name] => Jones )
[5623] => Array ( [id] => 5623 [first_name] => Peter [last_name] => Doe )
)
|
1.4 从对象中获取属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <?php class User { public $username;
public function __construct(string $username) { $this->username = $username; } }
$users = [ new User('user 1'), new User('user 2'), new User('user 3'), ];
print_r(array_column($users, 'username'));
|
结果为:
1 2 3 4 5 6
| Array ( [0] => user 1 [1] => user 2 [2] => user 3 )
|
2. array_filter
array_filter()
将删除 array 中所有等值为 FALSE
的条目。
1
| var_dump(array_filter([0, 0.0, '0', '', false, null, [], true, 123, '1']));
|
结果为:
1 2 3 4 5 6 7 8
| array(3) { [7] => bool(true) [8] => int(123) [9] => string(1) "1" }
|
如果使用回调函数,我们还可以做更多的事:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| <?php $employees = [ [ 'name' => 'John', 'age' => 45, 'language' => 'Python' ], [ 'name' => 'Robbin', 'age' => 25, 'language' => 'Golang' ], [ 'name' => 'Smith', 'age' => 35, 'language' => 'PHP' ], [ 'name' => 'Steven', 'age' => 29, 'language' => 'C#' ] ];
$fireList = array_filter( $employees, function ($employee, $key) use (&$employees) { return $employee['age'] > 35; }, ARRAY_FILTER_USE_BOTH );
print_r($fireList);
|
注意:用户不应在回调函数中修改数组本身。例如增加/删除单元或者对 array_filter()
正在作用的数组进行 unset
。如果数组改变了,此函数的行为将不可预测。
2. array_map
通过array_map()
,我们可以通过预设的函数对数组元素进行批量处理
1 2 3 4 5 6 7 8
| function cube($n) { return($n * $n * $n); }
$a = array(1, 2, 3, 4, 5); $b = array_map("cube", $a); print_r($b);
|
$b
将输出
1 2 3 4 5 6 7 8
| Array ( [0] => 1 [1] => 8 [2] => 27 [3] => 64 [4] => 125 )
|
从PHP 5.3起,我们也可以将调用的函数写作闭包的形式:
1 2 3 4 5 6
| $b = array_map( function ($n) { return($n * $n * $n); }, $a );
|
同样的,我们还可以使用系统内置的函数来处理一些数据,如:
1 2
| $values = ['say', ' bye', '', ' to', ' spaces ', ' ']; $result = array_map('trim', $values);
|
array_map()
也可以在类中使用,以下是在类中的调用方法
1 2 3 4 5 6 7 8 9 10 11 12
| array_map( array( 'ClassName', 'methodName' ), $array );
array_map( array( __CLASS__, 'methodName' ), $array ); array_map( array( 'self', 'methodName' ), $array );
array_map( array( $object, 'methodName' ), $array );
array_map( array( $this, 'methodName' ), $array );
|
3. array_reduce
求 1 ~ 100 的和:
1 2 3 4 5 6 7 8 9 10 11 12
| <?php $hunder = range(1, 100);
$sum = array_reduce( $hunder, function ($carry, $item) { $carry += $item; return $carry; } );
echo $sum;
|
4. array_walk
array_walk()
可以让我们便捷的修改数组内的元素:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| $infos = [ ['uid' => 1, 'email' => '[email protected]'], ['uid' => 2, 'email' => '[email protected]'] ];
array_walk( $infos, function (&$info) { $info['username'] = strstr($info['email'], '@', true); unset($info['email']); } );
echo json_encode($infos);
|
5. array_walk_recursive
把任意维度的数组转换成一维数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| $user = [ 'a' => [100, 'a1'], 'b' => [101, 'a2'], 'c' => [ 'd' => [102, 'a3'], 'e' => [103, 'a4'] ] ];
function array_flat($arr) { $result = []; array_walk_recursive($arr, function ($value) use (&$result) { array_push($result, $value); });
return $result; }
print_r(array_flat($user));
|
6. filter_var
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| var_dump(filter_var('[email protected]', FILTER_VALIDATE_EMAIL));
var_dump(filter_var('8.8.8.8', FILTER_VALIDATE_IP, FILTER_FLAG_IPV4));
var_dump(filter_var('2001:4860:4860::8888', FILTER_VALIDATE_IP, FILTER_FLAG_IPV6));
var_dump(filter_var('10.0.0.1', FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)); var_dump(filter_var('192.0.0.1', FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE));
var_dump(filter_var('8.8.8.8', FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE)); var_dump(filter_var('127.0.0.1', FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE)); var_dump(filter_var('0.0.0.0', FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE)); var_dump(filter_var('169.254.0.0', FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE)); var_dump(filter_var('255.255.255.255', FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE)); var_dump(filter_var('::1', FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE)); var_dump(filter_var('2002', FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE));
var_dump(filter_var('F1:5C:89:A4:40:49', FILTER_VALIDATE_MAC));
var_dump(filter_var('1', FILTER_VALIDATE_BOOLEAN));
var_dump(filter_var('1234.233', FILTER_VALIDATE_FLOAT)); var_dump(filter_var('1,234.233', FILTER_VALIDATE_FLOAT, FILTER_FLAG_ALLOW_THOUSAND));
|
7. array_multisort
通过array_multisort()
,可以让我们像操作 Excel 一样对数据进行排序操作,我们先来看一个简单的例子
7.1 多个数组排序
1 2 3 4 5 6
| $ar1 = array(10, 100, 100, 0); $ar2 = array(1, 3, 2, 4); array_multisort($ar1, $ar2);
var_dump($ar1); var_dump($ar2);
|
这个例子里,排序后,第一个数组会包含 0、 10、 100、 100。 第二个数组会包含 4、1、 2、 3。 第二个数组里的项目对应第一个数组后也进行了排序(100 和 100)。
1 2 3 4 5 6 7 8 9 10 11 12
| array(4) { [0]=> int(0) [1]=> int(10) [2]=> int(100) [3]=> int(100) } array(4) { [0]=> int(4) [1]=> int(1) [2]=> int(2) [3]=> int(3) }
|
7.2 对数据库结果进行排序
现在数据表中存储着如下的数据:
1 2 3 4 5 6 7 8
| volume | edition -------+-------- 67 | 2 86 | 1 85 | 6 98 | 2 86 | 6 67 | 7
|
我们将 volume 降序排列,把 edition 升序排列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| $data = [ ['volume' => 67, 'edition' => 2], ['volume' => 86, 'edition' => 1], ['volume' => 85, 'edition' => 6], ['volume' => 98, 'edition' => 2], ['volume' => 86, 'edition' => 6], ['volume' => 67, 'edition' => 7], ];
$volume = array_column($data, 'volume'); $edition = array_column($data, 'edition');
array_multisort($volume, SORT_DESC, $edition, SORT_ASC, $data);
|
数据集合现在排好序了,结果如下:
1 2 3 4 5 6 7 8
| volume | edition -------+-------- 98 | 2 86 | 1 86 | 6 85 | 6 67 | 2 67 | 7
|
8. array_merge
这个应该都很熟悉,就是将两个数组合并:
1 2 3
| $array1 = array("color" => "red", 2, 4); $array2 = array("a", "b", "color" => "green", "shape" => "trapezoid", 4); print_r(array_merge($array1, $array2));
|
输出
1 2 3 4 5 6 7 8 9 10
| Array ( [color] => green [0] => 2 [1] => 4 [2] => a [3] => b [shape] => trapezoid [4] => 4 )
|
⚠️:如果合并的数组中包含了关联数组,则相同键名元素会覆盖,且合并后的数组保留原键名。若是索引数组,则会重新生成索引。
同名关联数组被覆盖:
1 2 3
| $array1 = array("color" => "red"); $array2 = array("color" => "green", "shape" => "trapezoid"); print_r(array_merge($array1, $array2));
|
输出
1 2 3 4 5
| Array ( [color] => green [shape] => trapezoid )
|
同名索引数组重新索引:
1 2 3
| $array1 = array(2, 4); $array2 = array("a", "b", 4); print_r(array_merge($array1, $array2));
|
输出
1 2 3 4 5 6 7 8
| Array ( [0] => 2 [1] => 4 [2] => a [3] => b [4] => 4 )
|
还有另一种合并数组的方式:+
运算符,这种方式可以完全保留原有数组并将新的数组附加到后面。在两个数组中存在相同的键名时,第一个数组中的同键名的元素将会被保留,第二个数组中的元素将会被忽略
1 2 3 4
| $array1 = array(0 => 'zero_a', 2 => 'two_a', 3 => 'three_a'); $array2 = array(1 => 'one_b', 3 => 'three_b', 4 => 'four_b'); $result = $array1 + $array2; print_r($result);
|
输出
1 2 3 4 5 6 7 8
| Array ( [0] => zero_a [2] => two_a [3] => three_a [1] => one_b [4] => four_b )
|
9. array_merge_recursive
将相同 key
的不同数组中信息进行合并:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?php $baseInfo = [ 'jack' => [ 'age' => 22, 'tel' => '56710937' ], 'rose' => [ 'age' => 21, 'tel' => '578391038' ] ];
$extInfo = [ 'jack' => [ 'addrs' => 'NYC' ], 'rose' => [ 'addrs' => 'London' ] ];
echo json_encode(array_merge_recursive($baseInfo, $extInfo));
|
输出:
1 2 3 4 5 6 7 8 9 10 11 12
| { "jack":{ "age":22, "tel":"56710937", "addrs":"NYC" }, "rose":{ "age":21, "tel":"578391038", "addrs":"London" } }
|
10. range
生成指定区间的数组
指定步长为 10
1
| range(1, 100, 10); // [0,10,20,30,40,50,60,70,80,90,100]
|
如果起始值大于结束值,则会按照递减的顺序生成
1
| range(100, 0, 10); // [100,90,80,70,60,50,40,30,20,10,0]
|
三个参数也可以是浮点数
1
| range(12.8, 2.2, 2.5); // [12.8, 10.3, 7.8, 5.3, 2.8]
|
$start
和 $end
如果全部是字符串,那么会取两个字符串的第一个字母,并按照 ASCII 字母顺序表,取步长对应的值
1
| range('a', 'i'); // ["a","b","c","d","e","f","g","h","i"]
|
那么,我们如何使用range()
来输出 ASCII 的所有可见字符呢?,这在PHP中非常简单:
11. array_chunk
如果我们需要将一个数组拆分为多个数组,就可以通过array_chunk()
快速实现:
1 2 3 4 5 6 7
| <?php $input_array = array('a', 'b', 'c', 'd', 'e'); echo json_encode(array_chunk($input_array, 2)),PHP_EOL; echo json_encode(array_chunk($input_array, 2, true));
|
12. array_combine
现在有两个数组,我们希望一个数组的元素做key
,另一个数组的元素做value
,合并为一个数组:
1 2 3 4 5 6 7
| $a = array('green', 'red', 'yellow'); $b = array('avocado', 'apple', 'banana'); $c = array_combine($a, $b);
echo json_encode($c);
|
14. compact
15. array_diff & array_intersect
如果需要求数组元素的差集/交集,可以使用array_diff($array1, $array2[,$arrayn])
,这将返回存在于$array1
中而不存在其他 array 中值。
1 2 3 4 5 6 7 8
| <?php $array1 = array("a" => "green", "red", "blue", "red"); $array2 = array("b" => "green", "yellow", "red"); $diff = array_diff($array1, $array2); $intersect = array_intersect($array1, $array2);
echo json_encode($diff); echo json_encode($diff);
|
16. array_diff_key & array_intersect_key
顾名思义,使用键名计算数组的差集/交集,同样是返回存在于$array1
中而不存在与其他$array
中的值。
17. array_diff_assoc & array_intersect_assoc
该函数会将键名与元素都作为比较条件。
18. version_compare
默认情况下,在第一个版本低于第二个时,version_compare() 返回 -1;如果两者相等,返回 0;第二个版本更低时则返回 1。(类似于太空操作符)))
1
| echo version_compare('5.3.0', '7.1.4'); // -1
|
该函数用于格式化数字,能实现
- 是否保留小数
- 数字的精度
- 自定义千分位分隔符与小数点分隔符
1 2 3 4
| $num = 123456.789; echo number_format($num),PHP_EOL; echo number_format($num, 2),PHP_EOL; echo number_format($num, 1, ',', '/'),PHP_EOL;
|
20. trim
tirm()
可以去除字符串首尾处的空白字符(或者其他字符),如果没有指定待删除的字符列表,则会删除以下字符:
- “ “ (ASCII 32 (0x20)),普通空格符。
- “\t” (ASCII 9 (0x09)),制表符。
- “\n” (ASCII 10 (0x0A)),换行符。
- “\r” (ASCII 13 (0x0D)),回车符。
- “\0” (ASCII 0 (0x00)),空字节符。
- “\x0B” (ASCII 11 (0x0B)),垂直制表符。
通常情况下,我们都会指定删除的字符列表
1
| trim('@apple……', '@#¥%……');
|
tips: 该函数与array_map()
同时服用,效果更佳。