陷阱:如果您的第一个元素为 false,则您不知道它是否为空。
<?php
$a = array();
$b = array(false, true, true);
var_dump(reset($a) === reset($b)); //bool(true)
?>
所以不要依赖 false 返回值来判断数组是否为空。
(PHP 4, PHP 5, PHP 7, PHP 8)
reset — 将数组的内部指针设置为其第一个元素
array
输入数组。
返回第一个数组元素的值,如果数组为空则返回 false
。
版本 | 描述 |
---|---|
8.1.0 | 对 对象 调用此函数已弃用。请先使用 get_mangled_object_vars() 将 对象 转换为 数组,或者改用实现 Iterator 接口的类的提供的 方法,例如 ArrayIterator。 |
7.4.0 | SPL 类的实例现在被视为没有属性的空对象,而不是调用与此函数同名的 Iterator 方法。 |
示例 #1 reset() 示例
<?php
$array = array('第一步', '第二步', '第三步', '第四步');
// 默认情况下,指针位于第一个元素
echo current($array) . "<br />\n"; // "第一步"
// 跳过两步
next($array);
next($array);
echo current($array) . "<br />\n"; // "第三步"
// 重置指针,从第一步重新开始
reset($array);
echo current($array) . "<br />\n"; // "第一步"
?>
陷阱:如果您的第一个元素为 false,则您不知道它是否为空。
<?php
$a = array();
$b = array(false, true, true);
var_dump(reset($a) === reset($b)); //bool(true)
?>
所以不要依赖 false 返回值来判断数组是否为空。
由于 reset() 除了重置其内部指针外还会返回数组的第一个“值”;当它与 key() 组合使用或单独使用时,它将返回不同的结果。例如:
<?php
$products = array(
'饼干' => array('饼干1' => 'cobis', '饼干2' => 'probis'),
'巧克力' => array('coco1' => 'cococ', 'coco2' => 'prococ'),
);
echo key(reset($products['饼干'])); // 致命错误
reset($products['饼干']);
echo key($products['饼干']); // 将打印 '饼干1'
?>
这是完全正常的,因为在第一种方法中,reset() 返回了“饼干”元素的第一个“值”,即“cbosi”。因此 key(string) 将导致致命错误。而在第二种方法中,您只是重置了数组,而没有使用返回值;而是重置了指针,然后提取了数组的第一个键。
如果您的数组具有更多维度,它可能不会导致致命错误,但是当您组合使用 reset() 和 key() 或连续使用它们时,您将获得不同的结果。
至于获取数组的第一个键,先重置然后取键要比重置 ARRAY_KEYS 的结果(如 gardnerjohng at gmail dot com 所建议的那样)效率更高。
<?php
reset($someArray);
echo key($someArray);
?>
这将给出相同的结果,但速度要快得多。数组越大,性能越好。在包含 100 个元素的数组上进行了测试,结果速度提高了 16 倍。
回应 gardnerjohng 关于检索数组的第一个 _键_ 的备注
要检索数组的第一个 _键_,您可以组合使用 reset() 和 key()。
<?php
$properties = array(
'colour' => 'grey',
'flavour' => 'rubber',
'name' => 'Mouse Ball',
'texture' => 'rubbery'
);
reset($properties);
echo key($properties); // => 'colour'
?>
我更喜欢这个方案,因为它不需要创建键数组。这应该(未经测量)会提高大型数组的性能。
请注意,这里不能使用指针。在这种情况下,它会重置迭代计数器。
foreach($array as $key=>&$value) {...}
请改用标准的foreach循环
foreach($array as $key=>$value) {...}
这种方法也适用于重置多维数组
reset($voo2['moder']);
while (list($key, $value) = each ($voo2['moder'])) {
reset($voo2['moder'][$key]);
while (list($key1, $value1) = each ($voo2['moder'][$key])) {
#执行你想要的操作
}
}
请注意,reset()不会影响多维数组的子数组。
例如:
<?php
$arr = array(
1 => array(2,3,4,5,6),
2 => array(6,7,8,9,10)
);
while(list($i,) = each($arr))
{
echo "IN \$arr[$i]<br>";
while(list($sub_i,$entry) = each($arr[$i]))
{
echo "\$arr[$i][$sub_i] = $entry<br>";
}
}
reset($arr);
// 再次执行相同的操作
while(list($i,) = each($arr))
{
echo "IN \$arr[$i]<br>";
while(list($sub_i,$entry) = each($arr[$i]))
{
echo "\$arr[$i][$sub_i] = $entry<br>";
}
}
?>
将输出
IN $arr[1]
$arr[1][0] = 2
$arr[1][1] = 3
$arr[1][2] = 4
$arr[1][3] = 5
$arr[1][4] = 6
IN $arr[2]
$arr[2][0] = 6
$arr[2][1] = 7
$arr[2][2] = 8
$arr[2][3] = 9
$arr[2][4] = 10
IN $arr[1]
IN $arr[2]
信息
以下代码在5.4.45版本中会发出严格警告
return reset(array_keys($result['node']));
"严格警告:只有变量才能通过引用传递"
所以应该是
$keys = array_keys($result['node']);
return reset($keys);
不要使用`reset()`来获取关联数组的第一个值。它在普通数组中运行良好,但在迭代器对象中运行结果出乎意料。http://bugs.php.net/bug.php?id=38478
Colin,有一个更好的(在我看来)方法来解决你的问题。
<?
// ...
foreach($a as $k => &$d){} // 注意"&"
// ...
?>
这是PHP5中新增的功能,在foreach循环中使用引用。这样PHP就不会复制数组,因此内部指针不会被重置。
我在PHP 5.0.5中遇到一个问题,它在没有任何明显原因的情况下重置了数组的子数组。问题在于对父数组执行foreach()操作时,PHP会复制子数组,这样做会重置原始数组的内部指针。
以下代码演示了子数组的重置
<?
$a = array(
'a' => array(
'A', 'B', 'C', 'D',
),
'b' => array(
'AA', 'BB', 'CC', 'DD',
),
);
// 将$a的指针设置为'b',并将'b'的指针设置为'CC'
reset($a);
next($a);
next($a['b']);
next($a['b']);
next($a['b']);
var_dump(key($a['b']));
foreach($a as $k => $d)
{
}
var_dump(key($a['b']));
?>
这两个var_dump的结果分别是3和0。显然,通过对$a进行foreach循环,$a['b']的内部指针被重置了。
每次foreach循环迭代$a的'a'和'b'键时,它都会将$a['a']和$a['b']复制到$d中,这重置了$a['a']和$a['b']的内部指针,尽管没有进行明显的更改。
解决方案是改为迭代$a的键。
<?
foreach(array_keys($a) as $k)
{
}
?>
并使用$a[$k](或创建$a[$k]的别名$d并处理使用别名的后果)。
出于好奇,我在一个虚拟对象上实现Iterator接口,并调用一个全局对象来进行实际的迭代(也为了应对PHP缺乏C风格的指针,当对对象进行$a = $b操作时,当修改时$a中的数据与$b中的数据不一致)。由于我有许多表示不同数据集的虚拟对象,我选择将每个数据集存储为包含在全局对象中的子数组。为了使此工作,每个虚拟对象必须存储一个键(可以自由复制而不会出现问题),在虚拟对象上调用rewind、key、current、next和valid时,它会将该键传递给全局对象。
不幸的是,我的键不能仅仅是一个简单的字符串或数字(如果是的话,它可以直接索引该对象的数据子数组并避免问题),而是一个字符串数组。相反,我必须迭代(使用foreach循环)每个子数组并将键与存储在子数组中的变量进行比较。
因此,通过这种方式使用foreach循环,并且PHP重置子数组的指针,最终导致无限循环。
实际上,这可以通过PHP即使在复制后也能维护数组的内部指针来解决。