PHP数组函数总结

作为一门 Web 开发语言,PHP 无疑是成功的:

  1. 只需简单的学习便可快速上手
  2. 内置大量系统函数
  3. 动态解释型更快更灵活的应对业务快速迭代
  4. ……

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 作为$recordskey重新生成索引数组

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
// Static outside of class context
array_map( array( 'ClassName', 'methodName' ), $array );

// Static inside class context
array_map( array( __CLASS__, 'methodName' ), $array );
array_map( array( 'self', 'methodName' ), $array );

// Non-static outside of object context
array_map( array( $object, 'methodName' ), $array );

// Non-static inside of object context
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); // [{"uid":1,"username":"jack"},{"uid":2,"username":"rose"}]

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)); // 有效输出email地址,无效输出false

// 验证 IPv4
var_dump(filter_var('8.8.8.8', FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)); // 有效输出IP,无效输出false

// 验证 IPv6
var_dump(filter_var('2001:4860:4860::8888', FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)); // 有效输出IP,无效输出false

// 验证非私网 IP
var_dump(filter_var('10.0.0.1', FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)); // 非私网输出IP,否则输出false
var_dump(filter_var('192.0.0.1', FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE));

// 验证非保留 IP
var_dump(filter_var('8.8.8.8', FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE)); // // 非保留IP输出IP,否则输出false
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));

// 验证 Mac 地址
var_dump(filter_var('F1:5C:89:A4:40:49', FILTER_VALIDATE_MAC)); // 有效输出地址,无效输出 false

// 验证布尔值
var_dump(filter_var('1', FILTER_VALIDATE_BOOLEAN)); // 1, true, on ,yes 返回 true,否则返回 false

// 验证浮点数
var_dump(filter_var('1234.233', FILTER_VALIDATE_FLOAT)); // 有效输出浮点数,无效输出 false
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');

// 将数据根据 volume 降序排列,根据 edition 升序排列
// 把 $data 作为最后一个参数,以通用键排序
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

生成指定区间的数组

1
range(0, 100);

指定步长为 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中非常简单:

1
range(' ', '~');

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));

// [["a","b"],["c","d"],["e"]]
// [["a","b"],{"2":"c","3":"d"},{"4":"e"}]

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);

// {"green":"avocado","red":"apple","yellow":"banana"}

13. extract

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); // {"1":"blue"}
echo json_encode($diff); // {"a":"green","0":"red","2":"red"}

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

19. number_format

该函数用于格式化数字,能实现

  • 是否保留小数
  • 数字的精度
  • 自定义千分位分隔符与小数点分隔符
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……', '@#¥%……'); // apple

tips: 该函数与array_map()同时服用,效果更佳。

因为热爱,所以执着。