PHP 遍历数组
本文最后更新于:2024年3月18日 凌晨
PHP 遍历数组
- 数组中最普遍的任务是用每个元素完成一些事情,例如,发送邮件到地址数组的每个元素,更新文件名数组中的每个文件或将价格数组的每个元素值增值,在PHP中有几种方法来遍历数组,选择使用哪一种取决于你的数据和要执行的任务。
访问单个数组元素
- 在前面我们看到了创建一个数组,现在让我们来看看一个已经存在的数组的结构,可以用数组变量的名字后跟括在中括号中的元素键(有时也称作索引,index)来访问数组中特定的值。
- 键可以是一个字符串或一个整数,等价于整数(但不以零开头)的字符串值被当作整数对待,因此,$array[3]和$array[‘3’]引用相同的元素,但是$array[‘03’]引用另一个不同的元素,负数是有效的键,并且它们不像在Perl中那样从数组的末尾逆序地指定位置。
- 你不一定需要将单个词的字符串加上引号,例如,$age[‘Fred’]和$age[Fred]是相同的,但是,使用引号是很好的PHP风格,因为没有引号的键不能和常量区别开来,当你把一个常量当作无引号的索引使用时,PHP会把常量的值当作索引使用。
1 2
| define('index',5); echo $array[index];
|
- 如果要在键名中使用变量替换(variable interpolation,即解析)来建立数组索引,必须使用引号(这样才能进行变量解析):
- 但是,如果要通过变量替换得到某个数组元素,则键名不要使用引号:
1 2 3 4 5
| print "Hello, $person['name']"; print "Hello, $person["name"]";
print "Hello, $person[name]";
|
foreach
- 遍历数组元素最常用的方法是使用foreach结构:
1 2 3 4 5 6 7
| $addresses = array('spam@cyberpromo.net','abuse@example.com'); foreach($addresses as $value){ echo "Processing $value\n"; }
Processing spam@cyberpromo.net Processing abuse@example.com
|
- PHP为
$addresses
的每个元素依次执行循环体(echo语句)一次,将$value
赋值为当前元素的值,各元素按数组内部顺序进行处理。
- 另一种foreach格式可以让你访问当前元素的键名:
1 2 3 4 5 6 7 8
| $person = array('name' => 'Fred','age' => 35,'wife' => 'Wilma'); foreach($person as $key => $value){ echo "Fred's $key is $value\n"; }
Fred's name is Fred Fred's age is 35 Fred's wife is Wilma
|
- 在这种情况下,每个元素的键名被放在
$key
中,其对应的值放在$value
中。
- foreach结构并没有操作数组本身,而是操作数组的一份拷贝,在foreach循环体中插入或删除元素是安全的,因为循环并没有试图处理那些已经被删除或插入的元素。
迭代器函数
- 每个PHP数组都会跟踪当前所处理的元素,指向当前元素的指针被称为迭代器(iterator),PHP有一些函数来设置,移动和重置迭代器,迭代器函数有:
current()
返回迭代器当前指向的元素。
reset()
移动迭代器到数组的第一个元素并返回该元素。
next()
移动迭代器到数组的下一个元素并返回该元素。
prev()
移动迭代器到数组的上一个元素并返回该元素。
end()
移动迭代器到数组的最后一个元素并返回该元素。
each()
以数组的形式返回当前元素的键和值,并移动迭代器到数组的下一个元素。
key()
返回当前元素的键。
each()
函数用于遍历数组元素,该函数根据元素的内部顺序来处理元素:
1 2 3 4 5 6 7
| reset($addresses); while(list($key,$value = each($addresses)){ echo "$key is $value<BR>\n"; }
0 is spam@cyberpromo.net 1 is abuse@example.com
|
- 这种方法并没有像foreach那样产生数组的一个拷贝,处理大数组时如果想要节约内存,这种方法是很有用的。
- 当需要把数组的一部分分离出来的时候,迭代器函数时很有用的,实例5-1的代码创建一个表格,并把关联数组的第一个索引和值作为表格的列标题。
**示例5-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
| $ages = array('Person' => 'Age', 'Fred' => 35, 'Barney' => 30, 'Tigger' => 8, 'Pooh' => 40);
reset($ages); list($c1,$c2) = each($ages); echo("<table><tr><th>$c1</th></tr>\n");
while(list($c1,$c2) = each($ages)){ echo("<tr><td>$c1</td><td>$c2</td></tr>\n"); }
echo("</table>");
<table> <tr><th>Person</th><th>Age</th></tr> <tr><td>Fred</td><td>35</td></tr> <tr><td>Barney</td><td>30</td></tr> <tr><td>Tigger</td><td>8</td></tr> <tr><td>Pooh</td><td>40</td></tr> </table>
|
使用for循环
- 如果知道要处理的是一个索引数组,且它的键为从0开始的连续整数,那么可以使用一个for循环来遍历索引,for循环在数组本身操作,而不是在数组的拷贝上,并按照键的顺序来处理元素,而不考虑他们的内部顺序。
- 下面是如何使用for来打印一个数组:
1 2 3 4 5 6 7 8
| $addresses = array('spam@cyberpromo.net','abuse@example.com'); for($i = 0;$i < count($addresses);$i++){ $value = $addresses[i]; echo "value\n"; }
spam@cyberpromo.net abuse@example.com
|
为数组的每个元素调用函数
- PHP提供了一个函数
array_walk()
,用于为数组中的每个元素调用用户自定义函数:
1
| array_walk(array,function_name);
|
- 自定义的函数可选地接收 2个或3个参数:第一个是元素的值,第二个是元素的键,第三个是该函数被
array_walk()
调用时使用的值,例如,下面是把数组的值作为表格的列来打印的另一个方法:
1 2 3 4 5
| function print_row($value,$key){ print("<tr><td>$value</td><td>$key</td></tr>\n"); } $person = array('name' => 'Fred','age' => 35,'wife' => 'Wilma'); array_walk($person,'print_row');
|
- 可以对上示例进行改进,使用
array_walk()
可选的第三个参数来指定背景颜色,这个参数可让我们根据需要用多种背景颜色打印多个表格:
1 2 3 4 5 6 7
| function print_row($value,$key,$color){ print("<tr><td bgclolr=$color>$value</td><td bgcolor=$color>$key</td></tr>\n"); } $person = array('name' => 'Fred','age' => 35,'wife' => 'Wilma'); echo '<table border=1>'; array_walk($person,'print_row','lightblue'); echo '</table>';
|
array_walk()
函数按数组元素的内部顺序处理元素。
数组归纳
array_walk()
的近似函数array_reduce()
,将一个函数依次应用于数组的每个元素来得到单个值(这个操作书中称之为Reducing,即从一个数组中”浓缩"出一个值,译者将其译为归纳)
1
| $result = array_reduce(array,function_name[,default]);
|
- 这个函数有两个参数:实时总数值和将要处理的当前值,它将返回一个新的实时总数,例如,要计算数组值的平方和,可以使用:
1 2 3 4 5 6 7 8
| function add_up($running_total,$current_value){ $running_total += $current_value * $current_value; return $running_total; } $numbers = array(2,3,5,7); $total = array_reduce($numbers,'add_up'); echo $total;
|
1 2 3
| add_up(2,3) add_up(11,5) add_up(36,7)
|
- 如果提供了default参数,则将其作为种子值,例如,如果将前面例子中的
array_reduce()
调用改为:
1
| $total = array_reduce($numbers,'add_up',11);
|
1 2 3 4
| add_up(11,2) add_up(15,3) add_up(24,5) add_up(49,7)
|
- 如果数组是空的,
array_reduce()
返回default值,如果没有给定默认值并且数组为空,array_reduce()
返回NULL
查找元素值
in_array()
函数返回true或false,取决于第一个参数是否是第二个参数指定的数组中元素:
1
| if(in_array(to_find,array[,strict])){...}
|
- 如果可选的第三个参数是true,那么to_find的数据类型必须和数组的值相匹配,默认是不检查类型的,只检查值。
- 下面是一个简单的例子:
1 2 3
| $addresses = array('spam@cyberpromo.net','abuse@example.com','root@example.com'); $got_spam = in_array('spam@cyberpromo.net',$addresses); $got_milk = in_array(milk@tucows.com',$addresses);//$got_milk为false
|
- PHP自动索引数组的值,所以
in_array()
比使用循环检查数组的每个值来寻找一个值要快的多。
- 下例检查用户是否在表单中所有要求输入的字段内填入了信息。
示例5-2 :查找一个数组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?php function have_required($array,$required_fields){ foreach($required_fields as $field){ if(empty($array[$field])) return false; } return true; } if($submitted){ echo '<p>You '; echo have_required($_POST,array('name','email_address'))?'did':'did not'; echo ' have all the required fields.</p>'; } ?> <from action="<?=$PHP_SELF;?>"method="POST"> <p> Name:<input type="text" name="name" /><br/> Email address:<input type="text" name="age" /> </p> <p align="center"> <input type="submit" value="submit" name="submitted" /> </p> </form>
|
in_array()
的一个变种是array_search()
函数,如果值被找到,in_array()
返回true,而array_search()
返回找到元素的键:
1 2 3 4 5
| $person = array('name' => 'Fred','age' =>35,'wife' => 'Wilma'); $k = array_search($person,'Wilma'); echo ("Fred's $k is Wilma\n");
Fred's wife is Wilma
|
array_search()
函数也接收可选的第三个strict参数,如果设定为true的话,要查找的值和类型都要和数组中的相匹配。