Skip to content

数组

数组是在程序设计中,为了处理方便, 把若干变量按有序的形式组织起来的一种形式。

  • 按数组键值类型的不同,数组又可分为:数值索引数组字符关联数组

  • 数组中有几个索引值就被称为几维数组。

数组分类

在PHP中有两种数组:索引数组关联数组

  • 索引(indexed)数组的索引值是整数,以0开始。当通过位置来标识东西时用索引数组。
  • 关联(associative)数组以字符串做为索引值,类似操作表。索引值为列名,用于访问列的数据
php
$arr = [1, 2, 3]; // 索引数组
$users = ['name' => 'admin', 'age' => 1]; // 关联数组

读取数组元素

key - 从关联数组中取得键名

php
$arr = ['abc', 'xyz'];
echo key($arr); // 0

current - 返回数组中的当前单元

php
$arr = ['abc', 'xyz'];
echo current($arr); // abc

next - 返回数组下一个值

将数组中的内部指针向下移动一位,并返回值。没有更多单元时返回 FALSE

php
$arr = ['abc', 'xyz'];
echo next($arr); // xyz

prev - 返回数组上一个值

将数组的内部指针倒回一位,并返回值。没有更多单元时返回 FALSE

php
$arr = ['abc', 'xyz'];
var_dump(prev($arr)); // false

reset - 返回数组第一个元素

将内部指针指向数组中的第一个元素,并输出

php
$people = ['Peter', 'Joe', 'Glenn', 'Cleveland'];

echo current($people) . '<br/>'; // Peter
echo next($people) . '<br/>'; // Joe
echo reset($people); // Peter

指针遍历

php
$users = [
    ['name' => '小明', 'age' => 22],
    ['name' => '张三', 'age' => 19],
    ['name' => '李四', 'age' => 34],
];
?>
<table border="1">
    <tr>
        <th>编号</th>
        <th>姓名</th>
        <th>年龄</th>
    </tr>
    <?php while ($user = current($users)): ?>
        <tr>
            <td><?php echo key($users) + 1 ?></td>
            <td><?php echo $user['name'] ?></td>
            <td><?php echo $user['age'] ?></td>
        </tr>
        <?php next($users); endwhile; ?>
</table>

遍历数组

foreach

php
$array = [1, 2, 3];
foreach ($array as $key => $value) {
    echo $key . '=>' . $value . '<br/>';
}

list

  • 把数组中的值赋给一组变量
php
$array = ['admin', 'foo@foo.com'];
list($name, $email) = $array;
echo $name . ' : ' . $email; // admin : foo@foo.com
  • 直接显示第三个
php
$array = ['zhangsan', 'lisi', 'wangwu'];
list(, , $name) = $array;
echo $name; // wangwu
  • 使用键名
php
$users = [
    ['name' => '小明', 'age' => 22],
    ['name' => '张三', 'age' => 19],
    ['name' => '李四', 'age' => 34],
];

while (list('name' => $name, 'age' => $age) = current($users)) {
    echo "name: {$name} <br/>";
    next($users);
}

常用函数

array_push

将一个或多个单元压入数组的末尾,这是传址操作。

php
$users = ['user1', 'user2'];
array_push($users, 'user3');
print_r($users); // Array ( [0] => user1 [1] => user2 [2] => user3 )

array_pop

弹出数组最后一个单元(出栈),这是传址操作。

php
$users = ['user1', 'user2'];
array_pop($users);
print_r($users); // Array ( [0] => user1 )

array_shift

将数组开头的单元移出数组,这是传址操作。

php
$users = ['user1', 'user2'];
array_shift($users);
print_r($users); // Array ( [0] => user2 )

array_unshift

在数组开头插入一个或多个单元

php
$users = ['user1', 'user2'];
array_unshift($users, 'user0');
print_r($users); // Array ( [0] => user0 [1] => user1 [2] => user2 )

count

计算数组中的单元数目,或对象中的属性个数

php
$users = ['user1', 'user2'];
echo count($users); // 2

array_count_values

统计数组中所有的值

php
$prices_per_day = ['单床房' => 198, '标准间' => 268, '大床房' => 198, 'VIP套房' => 368];
print_r(array_count_values($prices_per_day));
// AArray ( [198] => 2 [268] => 1 [368] => 1 )

in_array

检查数组中是否存在某个值

php
$allowImageType = ['jpeg', 'jpg', 'png'];
$file = 'foo.txt';
$ext = strtolower(substr(strrchr($file, '.'), 1));
if (!in_array($ext, $allowImageType)) {
    echo 'is wrong';
}

array_key_exists

检查数组里是否有指定的键名或索引

php
$allowImageType = ['jpeg' => 100, 'jpg' => 200, 'png' => 300];
$file = 'foo.txt';
$ext = strtolower(substr(strrchr($file, '.'), 1));
if (!array_key_exists($ext, $allowImageType)) {
    echo 'is wrong';
}

array_keys

获取数组中所有的键名(返回数组)

php
$allowImageType = ['jpeg' => 100, 'jpg' => 200, 'png' => 300];
$file = 'foo.jpg';
$ext = strtolower(substr(strrchr($file, '.'), 1));
if (!in_array($ext, array_keys($allowImageType))) {
    echo 'is wrong';
}

array_filter

用回调函数过滤数组中的单元

php
$users = [
    ['name' => '张三', 'sex' => '男', 'age' => 20],
    ['name' => '李四', 'sex' => '女', 'age' => 33]
];

$result = array_filter($users, function ($user) {
    return $user['sex'] == '男';
});

print_r($result);

array_map

为数组的每个元素应用回调函数

php
$users = [
    ['name' => '张三', 'sex' => '男', 'age' => 20],
    ['name' => '李四', 'sex' => '女', 'age' => 33]
];

$result = array_map(function ($user) {
    unset($user['age']);
    return $user;
}, $users);

echo '<pre>';
print_r($result);

获取所有会员名称

php
$users = [
    ['name' => '张三', 'sex' => '男', 'age' => 20],
    ['name' => '李四', 'sex' => '女', 'age' => 33]
];

$result = array_map(function ($user) {
    return $user['name'];
}, $users);

echo '<pre>';
print_r($result);

array_unique

移除数组中重复的值

实现数组中元素的唯一性。也就是去掉数组中重复的元素。不管是数字索引数组还是联合索引数组,都是以元素值为准。

php
$user = [
    'real_name' => 'Token',
    'nick_name' => 'Token',
    'age' => 28,
];

// array_unique(array $array, int $flags = SORT_STRING): array
// 注意键名保留不变。如果指定了 flags 时存在多个相等的元素,会保留第一个相等的元素的键和值

var_dump(array_unique($user));  // 属性nick_name会被移除

array_values

返回数组中所有的值

php
$users = [
    ['name' => '张三', 'sex' => '男', 'age' => 20],
    ['name' => '李四', 'sex' => '女', 'age' => 33]
];

$result = array_map(function ($user) {
    return implode('-', array_values($user));
}, $users);

echo '<pre>';
print_r($result);

array_merge

合并一个或多个数组

php
$array1 = [1, 2];
$array2 = [3, 4];

$array = array_merge($array1, $array2);
print_r($array); // Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 )

关联数组中,相同键名,后面的会覆盖前面的

php
$array1 = ['host' => '127.0.0.1'];
$array2 = ['host' => 'localhost'];

$array = array_merge($array1, $array2);
print_r($array); // Array ( [host] => localhost )

array_change_key_case

将数组中的所有键名修改为全大写或小写

php
//键名转大写
$database = [
    'host' => 'localhost', 'port' => 3306
];
$result = array_change_key_case($database, CASE_UPPER);
print_r($result); // Array ( [HOST] => localhost [PORT] => 3306 )

//键名转小写
$database = [
    'Host' => 'localhost', 'Port' => 3306
];
$result = array_change_key_case($database, CASE_LOWER);
print_r($result); // Array ( [host] => localhost [port] => 3306 )

递归改变数组键名

php
$config = [
    'database' => ['host' => 'localhost', 'port' => 3306, 'user' => 'root'],
    'app' => ['name' => 'admin', 'url' => 'www.foo.com', 'app' => ['foo']]
];

function reset_array_change_key_case(array $data, int $type = CASE_UPPER): array
{
    foreach ($data as $k => $v):
        $action = $type == CASE_UPPER ? 'strtoupper' : 'strtolower';
        unset($data[$k]);
        $data[$action($k)] = is_array($v) ? reset_array_change_key_case($v, $type) : $v;
    endforeach;
    return $data;
}

echo '<pre>';
print_r(reset_array_change_key_case($config));

递归改变数组值

php
$config = [
    'database' => ['host' => 'localhost', 'port' => 3306, 'user' => 'root'],
    'app' => ['name' => 'admin', 'url' => 'www.foo.com', 'app' => ['foo']]
];

function reset_array_change_value_case(array $data, int $type = CASE_UPPER): array
{
    foreach ($data as $k => $v):
        $action = $type == CASE_UPPER ? 'strtoupper' : 'strtolower';
        $data[$k] = is_array($v) ? reset_array_change_value_case($v, $type) : $action($v);
    endforeach;
    return $data;
}

echo '<pre>';
print_r(reset_array_change_value_case($config));

array_walk_recursive

对数组中的每个成员递归地应用用户函数,本函数会递归到更深层的数组中去。下面是改变数组键值的操作。

php
$config = [
    'database' => ['host' => 'localhost', 'port' => 3306, 'user' => 'root'],
    'app' => ['name' => 'admin', 'url' => 'www.foo.com', 'app' => ['foo']]
];

function change_array_value(array $data, int $type = CASE_UPPER): array
{
    array_walk_recursive($data, function (&$value, $key, $type) {
        $action = $type == CASE_UPPER ? 'strtoupper' : 'strtolower';
        $value = $action($value);
    }, $type);
    return $data;
}

echo '<pre>';
print_r(change_array_value($config));

var_export

输出或返回一个变量的字符串表示,第二个参数为 TRUE 时返回字符串。

提示

此场景适合用于,首次站点部署,引导页系统配置后,生成配置文件

php
<?php

/**
 * 把array()转为[]显示
 * @param $expression array 数组
 * @param false $return bool 是否输出,TRUE 输出 FALSE 打印
 * @return string|string[]|null
 */
function varExport($expression, $return = FALSE)
{
    $export = var_export($expression, TRUE);
    $patterns = [
        "/array \(/" => '[',
        "/^([ ]*)\)(,?)$/m" => '$1]$2',
        "/=>[ ]?\n[ ]+\[/" => '=> [',
        "/([ ]*)(\'[^\']+\') => ([\[\'])/" => '$1$2 => $3',
    ];
    $export = preg_replace(array_keys($patterns), array_values($patterns), $export);
    if ((bool)$return) return $export; else echo $export;
}

$config = [
    'database' => ['host' => 'localhost', 'port' => 3306, 'user' => 'root'],
    'app' => ['name' => 'admin', 'url' => 'www.foo.com', 'app' => ['foo']]
];

// 生成合法的PHP代码
$configContent = "<?php\n\nreturn " . varExport($config, TRUE) . ';';
file_put_contents('database.php', $configContent);

此时,会在该目录下生成一个database.php文件,内容如下:

php
<?php

return [
  'database' => [
    'host' => 'localhost',
    'port' => 3306,
    'user' => 'root',
  ],
  'app' => [
    'name' => 'admin',
    'url' => 'www.foo.com',
    'app' => [
      0 => 'foo',
    ],
  ],
];

serialize

将数组序列化为字符串。

php
$config = [
    'database' => ['host' => 'localhost', 'port' => 3306, 'user' => 'root'],
    'app' => ['name' => 'admin', 'url' => 'www.foo.com', 'app' => ['foo']]
];

echo serialize($config);

unserialize

从已存储的表示中创建 PHP 的值

php
$config = [
    'database' => ['host' => 'localhost', 'port' => 3306, 'user' => 'root'],
    'app' => ['name' => 'admin', 'url' => 'www.foo.com', 'app' => ['foo']]
];

function cache(string $name, array $data = null)
{
    $file = md5($name) . '.php';
    if (is_null($data)) {
        $content = is_file($file) ? file_get_contents($file) : null;
        return unserialize($content) ?: null;
    } else {
        return file_put_contents($file, serialize($data));
    }
}

cache('database', $config);
var_dump(cache('database'));
最近更新