Oracle 技术网
PHP 编程
第 5 章:数组

Kevin Tatroe 与 Rasmus Lerdorf 合著
摘自书籍 PHP 编程O'Reilly & Associates,2002 年 3 月)

下载 选自该书的代码示例

如第 2 章所述,PHP 支持标量和组合数据类型。在本章中,我们将讨论其中的一种组合类型:数组。数组是数据值的集合,由键值对的有序集合构成。

本章讨论创建数组、从数组中添加和删除元素,以及遍历数组中的元素。在 PHP 中有许多内建的函数与数组有关,因为数组非常普遍而且有用。例如,如果您想向多个地址发送电子邮件,您可以把电子邮件地址存储在一个数组中,然后循环访问该数组,把消息发送到当前的邮件地址。另外,如果一个表单允许多项选择,用户选择的选项就存放在一个数组中返回。

索引数组与关联数组的比较

在 PHP 中有两种数组:索引数组与关联数组。索引数组的键是从 0 开始的整数。当通过位置识别事物时使用索引数组。关联数组以字符串为键,并且它更象两列的表。第一列是键,它用于访问数组值。

PHP 在内部将所有数组都存储为关联数组,因此关联数组和索引数组的唯一差别在于键是什么。一些数组特性主要是供索引数组使用的,因为它们假设数组的键是由 0 开始的连续整数。在这两种情况中,键都是唯一的 — 也就是说,不管键值是字符串还是整数,不可能有两个元素的键是相同的。

PHP 数组元素有独立于键和值的内部次序,有一些函数可以基于这些内部次序对数组进行遍历。该次序通常是值插入数组的先后次序,但是后面讲述的排序函数可以根据键、值或任何其它方法改变该次序。

确定数组元素

您可以通过在数组变量名后加带方括号的元素键(有时称为索引)来访问数组中的特定元素:

$age['Fred']
$shows[2]

键可以是字符串或整数。与整数数字等价(开头没有零)的字符串值被当作整数对待。因此,$array[3]$array['3'] 指向同一元素,但 $array['03'] 指向不同的元素。负数是有效的键,但它们不象在 Perl 中那样指向从数组末尾开始的位置。

一个单词的字符串可以不使用引号。例如,$age['Fred']$age[Fred] 是相同的。但是,良好的 PHP 风格总是使用引号,因为不带引号的键难以与常量相区别。当使用常量作为一个不带引号的索引时,PHP 使用该常量的值作为索引:

define('index',5);
echo $array[index];               // retrieves $array[5], not $array['index'];
如果插入一个值来构建数组索引,必须使用引号:

$age["Clone$number"]
但是,如果插入一个数组元素查询,则不使用引号:

// these are wrong
print "Hello, $person['name']";
print "Hello, $person["name"]";

// this is right
print "Hello, $person[name]";
在数组中存储数据

将值存入数组时,如果该数组不存在则将创建数组,但是如果试图从一个还未定义的数组中读取值则不会创建该数组。例如:

// $addresses not defined before this point
echo $addresses[0];                    // prints nothing
echo $addresses;                       // prints nothing

$addresses[0] = 'spam@cyberpromo.net';
echo $addresses;                       // prints "Array"
在程序中使用简单赋值来初始化一个数组会产生这样的代码:

$addresses[0] = 'spam@cyberpromo.net';
$addresses[1] = 'abuse@example.com';
$addresses[2] = 'root@example.com';
// ...
以上是索引数组,使用从 0 开始的整数索引。下面是一个关联数组:

$price['Gasket'] = 15.29;
$price['Wheel']  = 75.25;
$price['Tire']   = 50.00;
// ...
一个更简单的初始化数组的方法是使用 array( ) 结构,它根据参数构造数组:

$addresses = array('spam@cyberpromo.net', 'abuse@example.com',
                   'root@example.com');
使用 array( ) 创建关联数组时,使用 => 符号来分隔索引和值:

$price = array('Gasket' => 15.29,
               'Wheel'  => 75.25,
               'Tire'   => 50.00);
注意空格和对齐方式的使用。我们可以将代码写在一行上,但是那样不易于阅读:

$price = array('Gasket'=>15.29,'Wheel'=>75.25,'Tire'=>50.00);
要想构造一个空数组,则不要向 array( ) 传递参数:

$addresses = array(  );
可以使用 => 指定一个初始键然后跟随一列值。从该键开始将这些值插入数组,随后的值依次使用后续的键:

$days = array(1 => 'Monday',   'Tuesday', 'Wednesday',
                   'Thursday', 'Friday',  'Saturday', 'Sunday');
// 2 is Tuesday, 3 is Wednesday, etc.
如果初始索引是非数字的字符串,那么后续的索引是由 0 开始的整数。因此,下面的代码可能产生错误:

$whoops = array('Friday' => 'Black', 'Brown', 'Green');
// same as
$whoops = array('Friday' => 'Black', 0 => 'Brown', 1 => 'Green');
向数组末尾添加值

要向现有的索引数组末尾插入更多值,使用 [] 语法:

$family = array('Fred', 'Wilma');
$family[] = 'Pebbles';                 // $family[2] is 'Pebbles'
该结构假设数组的索引是数字,并将元素赋值给下一个可用的数字索引,从 0 开始。尝试向关联数组追加元素,在编程中人们几乎总是犯这种错误,但是 PHP 将为新元素提供一个数字索引而不会发出警告:

$person = array('name' => 'Fred');
$person[] = 'Wilma';                   // $person[0] is now 'Wilma'
分配一组值

range( ) 函数创建一个数组,数组元素是传递给它的两个参数之间的连续整数或字符值。例如:

$numbers = range(2, 5);                // $numbers = array(2, 3, 4, 5);
$letters = range('a', 'z');            // $numbers holds the alphabet
$reversed_numbers = range(5, 2);       // $numbers = array(5, 4, 3, 2);
只有字符串参数的第一个字母用于构建元素范围:

range('aaa', 'zzz')                    /// same as range('a','z')
获取数组大小

count( )sizeof( ) 函数的用法和效果都是相同的。它们返回数组中元素的个数。从风格上来看,不存在优先使用哪个函数。下面是一个例子:

$family = array('Fred', 'Wilma', 'Pebbles');

$size = count($family);              // $size is 3
这两个函数不考虑任何可能出现的数字索引:

$confusion = array( 10 => 'ten', 11 => 'eleven', 12 => 'twelve');
$size = count($confusion);      // $size is 3
填充数组

要创建一个初始为同一个值的数组,使用 array_pad( ) 函数。array_pad( ) 的第一个参数是数组,第二个参数是您希望数组拥有的最小元素数目,而第三个参数是赋给所有元素的值。不管参数数组是什么,array_pad( ) 函数都返回一个新的已填充数组。

下面是 array_pad( ) 的应用:

$scores = array(5, 10);
$padded = array_pad($scores, 5, 0);    // $padded is now array(5, 10, 0, 0, 0)

注意新的值是如何追加到数组末尾的。如果想把新值添加到数组的开头,则第二个参数使用负值:

$padded = array_pad($scores, -5, 0);
array_pad( ) 的结果赋值给原始数组能够获得在原处进行更改的效果:

$scores = array_pad($scores, 5, 0);
如果填充一个关联数组,现有的键将会保留。新的元素将会具有从 0 开始的数字键。

多维数组

数组的值本身也可以是数组。这使您可以很容易地创建多维数组:

$row_0 = array(1, 2, 3);
$row_1 = array(4, 5, 6);
$row_2 = array(7, 8, 9);
$multi = array($row_0, $row_1, $row_2);
可以通过追加更多 [] 来指向多维数组的元素:

$value = $multi[2][0];                 // row 2, column 0. $value = 7
要想在语句中插入多维数组元素,必须将整个多维数组放置在花括号中:

echo("The value at row 2, column 0 is {$multi[2][0]}\n");
不使用花括号会有这样的输出:

The value at row 2, column 0 is Array[0]
提取多个值

要把数组的所有值都复制到变量中,使用 list( ) 结构:

list($variable, ...) = $array;
数组的值依照其内部次序被复制到列出的变量中。默认情况下是其插入数组的先后次序,但是后面讲述的排序函数可以改变该次序。下面是一个例子:

$person = array('name' => 'Fred', 'age' => 35, 'wife' => 'Betty');
list($n, $a, $w) = $person;            // $n is 'Fred', $a is 35, $w is 'Betty'
如果数组中的值多于 list( ) 中的变量,多余的值被忽略:

$person = array('name' => 'Fred', 'age' => 35, 'wife' => 'Betty');
list($n, $a) = $person;                // $n is 'Fred', $a is 35
如果 list( ) 中的变量多于数组中的值,多余的变量值被设置为 NULL

$values = array('hello', 'world');
list($a, $b, $c) = $values;            // $a is 'hello', $b is 'world', $c is NULL
list( ) 中两个或更多连续的逗号能够跳过数组中的值:

$values = range('a', 'e');
list($m,,$n,,$o) = $values;            // $m is 'a', $n is 'c', $o is 'e'
分割数组

若只提取数组的一个子集,使用 array_slice( ) 函数:

$subset = array_slice(array, offset, length);
array_slice( ) 函数返回一个新的数组,包含原数组中一段连续的值。offset 参数指明要复制的起始元素(0 代表数组中的第一个元素),length 参数指明要复制的值的个数。新的数组具有从 0 开始的连续数字键。例如:

$people = array('Tom', 'Dick', 'Harriet', 'Brenda', 'Jo');
$middle = array_slice($people, 2, 2); // $middle is array('Harriet', 'Brenda')
通常只有在索引数组上使用 array_slice( ) 才有意义(也就是说那些具有从 0 开始的连续整数索引的数组):

// this use of array_slice(  ) makes no sense
$person = array('name' => 'Fred', 'age' => 35, 'wife' => 'Betty');
$subset = array_slice($person, 1, 2);  // $subset is array(0 => 35, 1 => 'Betty')
组合使用 array_slice( )list( ),仅将部分值提取到变量中:

$order = array('Tom', 'Dick', 'Harriet', 'Brenda', 'Jo');
list($second, $third) = array_slice($order, 1, 2);
// $second is 'Dick', $third is 'Harriet'
将数组分块

要将一个数组分为多个更小的、大小一样的数组,使用 array_chunk( ) 函数:

$chunks = array_chunk(array, size [, preserve_keys]);
该函数返回这些小数组中的一个数组。第三个参数 preserve_keys ,是一个布尔值,它决定新数组中的元素是保留原始数组中同样的键(对关联数组有用),还是具有新的从 0 开始的数字键(对索引数组有用)。默认设置是分配新键,如下所示:

$nums = range(1, 7);
$rows = array_chunk($nums, 3);
print_r($rows);
Array
(
    [0] => Array
        (
            [0] => 1
            [1] => 2
            [2] => 3
        )
    [1] => Array
        (
            [0] => 4
            [1] => 5
            [2] => 6
        )
    [2] => Array
        (
            [0] => 7
        )
)
键值对

array_keys( ) 函数返回一个仅由数组中的键组成的数组,它们以内部次序排列:

$array_of_keys = array_keys(array);
下面是一个例子:

$person = array('name' => 'Fred', 'age' => 35, 'wife' => 'Wilma');
$keys = array_keys($person);      // $keys is array('name', 'age', 'wife')
PHP 还提供了一个(通常作用较小)函数来获取数组中的值,array_values( )

$array_of_values = array_values(array);
array_keys( ) 一样,这些值按照数组的内部次序返回:

$values = array_values($person);       // $values is array('Fred', 35, 'Wilma');
检查一个元素是否存在

要想检查数组中是否存在某个元素,使用 array_key_exists( ) 函数:

if (array_key_exists(key, array)) { ... }
该函数返回一个布尔值,指明第二个参数在第一个参数给出的数组中是否是一个有效键。

简单的如下表述是不充分的:

if ($person['name']) { ...}           // this can be misleading
即使数组中存在以 name 为键的元素,它的相应值也可能是错误的(即 0、NULL,或者空字符串)。因此应如下使用 array_key_exists( )

$person['age'] = 0;                    // unborn?
if ($person['age']) {
  echo "true!\n";
}
if (array_key_exists('age', $person)) {
  echo "exists!\n";
}
exists!
在 PHP 4.0.6 和更早的版本中,array_key_exists( ) 函数为 key_exists( )。原始名称仍被保留作为新名称的别名。

许多人喜欢使用 isset( ),如果元素存在且不为 NULL,该函数返回 true

$a = array(0,NULL,'');
function tf($v) { return $v ?"T" :"F"; }
for ($i=0; $i < 4; $i++) {
  printf("%d:%s %s\n", $i, tf(isset($a[$i])), tf(array_key_exists($i, $a)));
}
0: T T
1: F T
2: T T
3: F F
在数组中删除和插入元素

array_splice( ) 函数可以在数组中删除或插入元素:

$removed = array_splice(array, start [, length [, replacement ] ]);
我们将使用下面这个数组来观察 array_splice( ) 函数:

$subjects = array('physics', 'chem', 'math', 'bio', 'cs', 'drama', 'classics');
我们可以告诉 array_splice( ) 函数从位置 2 开始删除 3 个元素,从而删除 mathbio cs 元素:

$removed = array_splice($subjects, 2, 3);
// $removed is array('math', 'bio', 'cs')
// $subjects is array('physics', 'chem');
如果您省略了 length 参数,array_splice( ) 将删除到数组末尾的所有元素:

$removed = array_splice($subjects, 2);
// $removed is array('math', 'bio', 'cs', 'drama', 'classics')
// $subjects is array('physics', 'chem');
如果只想删除元素而不管它们的值,则无需把 array_splice( ) 的结果赋值。

array_splice($subjects, 2);
// $subjects is array('physics', 'chem');
要想在删除元素的地方插入新元素,使用第四个参数:

$new = array('law', 'business', 'IS');
array_splice($subjects, 4, 3, $new);
// $subjects is array('physics', 'chem', 'math', 'bio', 'law', 'business', 'IS')
替换数组的大小不必和删除的元素数目一样。数组根据需要增长或缩短:

$new = array('law', 'business', 'IS');
array_splice($subjects, 2, 4, $new);
// $subjects is array('physics', 'chem', 'math', 'law', 'business', 'IS')
要想获得向数组插入新元素的效果,可以删除零个元素:

$subjects = array('physics', 'chem', 'math');
$new = array('law', 'business');
array_splice($subjects, 2, 0, $new);
// $subjects is array('physics', 'chem', 'law', 'business', 'math')
虽然到现在为止的例子都使用索引数组,array_splice( ) 也可以在关联数组上使用。

$capitals = array('USA'           => 'Washington',
                  'Great Britain' => 'London',
                  'New Zealand'   => 'Wellington',
                  'Australia'     => 'Canberra',
                  'Italy'         => 'Rome');
$down_under = array_splice($capitals, 2, 2); // remove New Zealand and Australia
$france = array('France' => 'Paris');
array_splice($capitals, 1, 0, $france);      // insert France between USA and G.B.
下一页>> 共 3 页
寄送此页面
Printer View 打印机视图