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]; // 检索$array[5],而不是$array['index']
  • 如果要在键名中使用变量替换(variable interpolation,即解析)来建立数组索引,必须使用引号(这样才能进行变量解析):
1
$age["Clone$number"];
  • 但是,如果要通过变量替换得到某个数组元素,则键名不要使用引号:
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");
//print the rest of the values
// 打印其余值。
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;
// $total现在为87
  • array_reduce()行调用了下面的函数:
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_spam为true
$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的话,要查找的值和类型都要和数组中的相匹配。

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!