小池有话说

PHP 数组

2014-12-25

PHP 的数组即是list, 又是 dict(associate array). 不仅如此, list 和 dict 还可以混用.

比如, Pdo的 fetch_mode 设为 Pdo::FETCH_ASSOC 得到的数组是

array(
    'id' => '1',
    'name' => 'picasso',
)

如果设为 Pdo::FETCH_NUM 得到的数组是

array(
    1 => '1',
    2 => 'picasso',
)

如果设为 Pdo::fetch_all, 得到的数组是

array(
    1 => '1',
    'id' => '1',
    2 => 'picasso',
    'name' => 'picasso',
)

PHP的数组的下标只有两种类型 int 和string


坑!

如果你对数组

$a['1'] = 'foo';
$a[1] = 'foo'; // exactly the same
$a['1'] = 'bar'; // now $a[1] === 'bar'

在PHP中, array 的实现方式是 hash table. 因此 读写都是 O(1).

为了加深大家的印象

<?php

$a[2] = 'a'; // $a 并没有初始化, 但是也不会报 warning, 这个在 PHP 中是完全合法的!
$a[1] = 'b';
$a[] = 'c'; // $a[3] 不是 $a[0]

print_r($a);

foreach ($a as $k => $v) {
	echo "$k => $v\n"; // 顺序 a b c
}

判断一个数组是否拥有某个key 用

isset($arr[$key])

但是如果值为 null 则返回 false. array_key_exists 则不然.

在foreach中修改数组, 可以修改值

foreach ($arr as $key => $value) {
    $arr[$key] = $new_value;
}

foreach ($arr as $key => &$value) { // 可以不管 key
    $value = $new_value;
}

另一种遍历方式.

reset($arr);
while(key($arr) !== null) {
    $value = current($arr);
    next($arr);
    continue;
}

不要在 foreach 中unset一个值(这个不是PHP独有的坑).

reset($arr);
while(($key = key($arr)) !== null) {
    if (i_want()) {
        unset($arr[$key]);
    } else { // 注意这个 else, foreach 中 相当于没有这个 else
        next($arr);
        continue;
    }
}

当栈用

array_pop() array_push()

当队列用还要再加上

array_shift() array_unshift()

array_diff($a, $b) 相当于 $a - $b array_intersect($a, $b) 相当于 $a 和 $b 的交集

array_slice() 数组切片

list comprehension

array_map($func, $arr);
array_filter($arr, $func);

我知道参数顺序很坑爹. PHP的API设计规则就是 老子今天高兴. 当然, 有了map,就少不了著名的reduce

array_reduce($arr, $func);

array_map 可以作用于关联数组(dict)

array_map(function($e){return $e.'appendix';}, $arr);

但是 array_map 不会知道 key,所以,如果你想要这样

[k+'='+v for k,v in d.items()]

你可以用for循环或者

$func = function($k, $v) {return "$k=$v";};
array_map($func, array_keys($arr), array_values($arr)));

说到这里讲一下 字符串解析

"$a[42] $a[foo] {$a['foo']}"

"$this->prop {$this->method('hello')}" // what the fuck

in_array() 是线性时间的, 如果对一个大 array 反复调用的话, 可能会有性能问题.

$look_table = array_flip($arr); // 或者在一开始就将key value反过来
isset($look_table[$search_value]); // much faster

排序函数族


专辑: