PHP梳理之array

梳理 php 关于 array 的小知识,以后数组函数的应用尽量看这一篇文章

创建

  • 以下是正常的创建
1
2
3
4
<?php
$a = array(); // []
$b = []; // []
?>
  • 其他方式创建

  • range 创建一个纯数字的数组

  • explode,str_split 字符串分割成数组

  • array_map,array_filter 等数组函数,输入数组,返回新数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
$range0 = range(1, 10, 1); // [1,2,3,4,5,6,7,8,9,10]
$range1 = range(1, 10, 2); // [1,3,5,7,9]
$range2 = range(0, 10, 2); // [0,2,4,6,8,10]
$range3 = range(1, 10, 3); // [1,4,4,7,10]

$explode = explode(',', 'hi,guys'); // ['hi','guys']
$strSplit = str_split('what\'s up', 3); // ['wha', "t's", ' up'];

$a = [1,2,3,4];
$array = array_filter($a, function ($item) {
return $item % 2 == 0;
}); // [1 => 2, 3 => 4]

$b = array_map(function ($item) {
return $item * 2;
}, $a); // [2,4,6,8]
?>

常用函数

我们先定义一个数组方便我们操作

1
2
3
4
5
6
7
8
9
<?php
$data = [
0 => ['id' => 1, 'name' => 'Jack', 'user_id' => 12, 'age' => 12],
1 => ['id' => 2, 'name' => 'Tom', 'user_id' => 14, 'age' => 18],
2 => ['id' => 3, 'name' => 'James', 'user_id' => 13, 'age' => 16],
3 => ['id' => 4, 'name' => 'Jone', 'user_id' => 16, 'age' => 15],
5 => ['id' => 5, 'name' => 'Tom', 'user_id' => 14, 'age' => 18],
]; // 后续部分示例会参照这个数组进行操作
?>

很多场景下需要用到的函数

二维数组取出某一列(键值对)

array_column 提供了很完美的解决方法。

  • 我们可以在此方法的第二个参数传入要取出的列名,即可以拿到对应的列。
  • 我们还可传入第三个参数,也是一个列名,作为键名
  • 我们传入了第三个参数时,甚至可以把第二个参数设为null,这样我们取出了所有列

注意:传入的键名中,如果有重复的键的话,去后者,也就是说会有覆盖的情况所以谨慎行事

1
2
3
4
5
<?php
$userIds = array_column($data, 'user_id'); // 取出 user_id 列
$userNameDictByUserId = array_column($data, 'name', 'user_id'); // 取出 name 列,以 user_id 为键
$dataDictByUserId = array_column($data, null, 'user_id'); // 取出所有列,并以 user_id 为键,注意如果有相同的键,取后者所以在本列中 id = 2 的 Tom 不会出现(被 id = 5 的数据覆盖)
?>
数组去重

如上文中的 $userIds 可以用 array_unique 去重。

1
2
3
<?php
$userIdDict = array_unique($userIds);
?>
数组索引自然化

如上文中的 $userIdDict 虽然去重了,但是依然保留了原有的键,我们希望键名是数字索引且依次递增的。这时候可以用上 array_value

1
2
3
<?php
$userIdDictReIndex = array_values($userIdDict);
?>

注意:array_values并不是改变原数组的索引,而是返回了所有数组的值,所以我们需要一个行的数组来接收它

数组获取键

上文中,我们拿到了不重复的 $userIdDict,我们还可以通过 array_keys 来获取相同的结果

array_key 甚至还可以用来搜索键。

1
2
3
4
5
6
<?php
$otherUserIdDict = array_keys($userNameDictByUserId);
$otherUserIdDictSearch = array_keys($userNameDictByUserId, '13'); // [2]
$otherUserIdDictStrictSearch = array_keys($userNameDictByUserId, '13', true); // []
$otherUserIdDictStrictSearch = array_keys($userNameDictByUserId, 13, true); // [2]
?>
数组判断
  • 用 array_key_exists 来判断数组的键是否存在,也可以用 isset
  • 用 in_array 来判断某个值是否在数组中
  • 用 array_search 来查询某个值的键
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
array_key_exists(1, $userIdDictReIndex); // true
array_key_exists(5, $userIdDictReIndex); // false

isset($userIdDictReIndex[1]); // true
isset($userIdDictReIndex[5]); // false

in_array(14, $userIdDictReIndex); // true
in_array(15, $userIdDictReIndex); // false

array_search(16, $userIdDictReIndex); // 3
array_search(17, $userIdDictReIndex); // false
?>
数组过滤
  • 用 array_filter 过滤数组
1
2
3
4
5
6
7
<?php
$a = [1, 2, 3, 4];

$b = array_filter($a, function ($item) {
return $item % 2 == 0;
}); // $b = [1 => 2, 3 => 4];
?>
数组合并,截取,替换
  • 用 array_merge 合并数组
  • 用 array_slice 截取数组
  • 用 array_splice 替换(移除)数组的部分单元
  • 用 array_replace 逐个替换数组单元
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
$a = [1, 2];
$b = [3, 4];

$c = array_merge($a, $b); // [1,2,3,4]
$d = array_slice($c, 2, 2); // [3, 4]
$e = array_slice($c, 1, 2, true); // [1 => 2, 2 => 3]

$f = array_splice($c, 1, 2, null); // $c = [1, 4], $f = [2, 3]
$j = array_splice($c, 1, 1, [5, 6]);// $c = [1, 5, 6], $j = [4]

$h = array_replace($f, [1]); // $k = [1, 3]
$k = array_replace($f, [1, 2]); // $k = [1, 2]
$l = array_replace($k, [3, 4], [5, 6, 7]); // $j = [5, 6, 7]
?>
数组入栈,出栈
  • 用 array_push 在数组末尾插入(一|多)个单元
  • 用 array_pop 弹出数组末尾一个单元
  • 用 array_unshift 在数组开头插入(一|多)个单元
  • 用 array_shift 弹出数组开头一个单元
1
2
3
4
5
6
7
8
9
10
11
12
<?php
$a = [1, 2];
$b = [3, 4];

$c = array_merge($a, $b); // [1,2,3,4]
array_push($c, 5); // $c = [1,2,3,4,5]
$d = array_pop($c); // $c = [1,2,3,4], $d = 5
$e = array_shift($c); // $c = [2,3,4], $e = 1
array_unshift($c, 10); // $c = [10,2,3,4]
// 当然,最简单的入栈是这样的
$c[] = 5; // $c = [10,2,3,4,5]
?>
数组的地址变动
  • 用 current 获取当前单元
  • 用 next 切换数组地址为数组下一个单元
  • 用 prev 切换数组地址为数组上一个单元
  • 用 end 切换数组地址为数组末尾单元
  • 用 reset 切换数组地址为数组开头单元
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
$a = [1,2,3,4,5];

$b = current($a)); // 1
$c = next($a)); // 2
$d = prev($a)); // 1
$e = end($a); // 5
$f = next($a)); // false
$i = reset($a); // 1
$j = prev($a); // false
$k = current($a); // false

// 可以写成简单的循环
$arr = [1, 2, 3, 4];
while(true) {
$current = current($a);
if ($current) {
next($a);
continue;
}
break;
}
?>
数组的解构和展开
  • 用 list 来展开数组(仅限数字索引数组)
1
2
3
4
<?php
$arr = [1, 3, 5];
list ($first, $second, $third) = $arr; // $first = 1, $second = 3, $third = 5
?>

题外话,一个面试题:$a = 1, $b = 2; 用一句话交换两个变量的值,即:$a = 2, $b = 1;

解答:

1
2
list($a, $b) = [$b, $a];
// [$a, $b] = [$b, $a];
  • 用 extract 来解构数组

使用此函数需要保证局部上下文解构变量未命名

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?php
$arr = [
'a' => 1,
'b' => 2,
'c' => 3,
];

/**
* 最好写上注释,去除 ide 的报错提示
*
* @var int $a
* @var int $b
* @var int $c
*/
extract($arr);

echo $a . PHP_EOL; // 1
echo $b . PHP_EOL; // 2
echo $c . PHP_EOL; // 3

$f = 10;
$arr1 = [
'd' => 5,
'f' => 6
];

/**
* @var int $d
* @var int $f
*/
extract($arr1);

echo $d . PHP_EOL; // 5
echo $f . PHP_EOL; // 6 这里覆盖了

unset($d);
$f = 20;

/**
* 不覆盖,加入变量前缀
*
* @var int $d
* @var int $f
* @var int $pre_d
* @var int $pre_f
*/
$cc = extract($arr1, EXTR_PREFIX_IF_EXISTS, 'pre');

echo $d . PHP_EOL; // 5
echo $f . PHP_EOL; // 20
echo $pre_f . PHP_EOL; // 6
?>
  • 用 compact 来创建键值对数组
1
2
3
4
5
6
7
<?php
$a = 1;
$b = 2;
$c = 3;

$d = compact('a', 'b', 'c'); // ['a' => 1, 'b' => 2, 'c' => 3]
?>
数组统计类函数
  • array_sum 求和
  • min 取出最小值
  • max 取出最大值
  • count 数组长度
1
2
3
4
5
6
7
8
<?php
$arr = [1, 3, 5];

echo array_sum($arr) . PHP_EOL; // 9
echo min($arr) . PHP_EOL; // 1
echo max($arr) . PHP_EOL; // 5
echo count($arr) . PHP_EOL; // 3
?>

To be continue