从 PHP 7.2 开始,“each” 函数已被弃用,因此我发布的 has_next 已经不再是一个好主意了。这里还有一个更简单快捷的方法
<?php
function has_next(array $_array)
{
return next($_array) !== false ?: key($_array) !== null;
}
?>
(PHP 4, PHP 5, PHP 7, PHP 8)
next — 推进数组的内部指针
next() 的行为类似于 current(),只有一点不同。在返回元素值之前,它会将内部数组指针向前移动一个位置。这意味着它返回下一个数组值并将内部数组指针向前移动一个位置。
返回内部数组指针指向的下一个位置的数组值,如果不再有元素,则返回false
。
版本 | 描述 |
---|---|
8.1.0 | 对对象调用此函数已弃用。请先使用get_mangled_object_vars()将对象转换为数组,或者使用实现Iterator的类的提供的方法,例如ArrayIterator。 |
7.4.0 | SPL类的实例现在被视为没有属性的空对象,而不是调用与该函数同名的Iterator方法。 |
示例 #1 next() 及其相关函数的使用示例
<?php
$transport = array('foot', 'bike', 'car', 'plane');
$mode = current($transport); // $mode = 'foot';
$mode = next($transport); // $mode = 'bike';
$mode = next($transport); // $mode = 'car';
$mode = prev($transport); // $mode = 'bike';
$mode = end($transport); // $mode = 'plane';
?>
从 PHP 7.2 开始,“each” 函数已被弃用,因此我发布的 has_next 已经不再是一个好主意了。这里还有一个更简单快捷的方法
<?php
function has_next(array $_array)
{
return next($_array) !== false ?: key($_array) !== null;
}
?>
不要将 next 与 continue 混淆!
如果您是一位从 Perl 转向 PHP 的开发者,您可能会尝试在循环中使用 "next" 来跳过到下一个迭代……
例如:
foreach ($things as $thing) {
if (something I don't like about $thing) {
next;
}
blah....
}
PHP 编译器会接受 next... 但它不会工作。
请改用这个
foreach ($things as $thing) {
if (something I don't like about $thing) {
continue;
}
blah....
}
这段代码返回指定键的相邻元素。如果它没有相邻元素,则结果将为空。我的方法是使用键的顺序来确定相邻元素,这与仅获取数组中的下一个/上一个元素不同。随意指出愚蠢之处 :)
<?php
function array_neighbor($arr, $key)
{
krsort($arr);
$keys = array_keys($arr);
$keyIndexes = array_flip($keys);
$return = array();
if (isset($keys[$keyIndexes[$key]-1]))
$return[] = $keys[$keyIndexes[$key]-1];
if (isset($keys[$keyIndexes[$key]+1]))
$return[] = $keys[$keyIndexes[$key]+1];
return $return;
}
?>
此函数将返回关联数组中数组条目之前的、下一个相邻元素。如果指定的 $key 指向数组的最后一个或第一个元素,则将连续返回数组的第一个或最后一个键。这是前面发布的同一函数的改进版本。
<?php
function array_neighbor($count, $key = null, $arRelated = array(), $cntRelated = 2)
{
if($count > 0 && isset($key))
{
$keyL = $count - 1;
$keyR = 1;
$arResult = array();
for($i = 1; $i <= $cntRelated; $i++)
{
if($key == 0)
{
if(($i % 2) == 0)
{
$curKey = $count - $keyL;
$keyL--;
}
else
{
$curKey = $count - $keyR;
$keyR++;
}
}
else
{
if($arRelated[$i] >= $count - 1)
{
$curKey = 0;
}
else
{
$curKey = $arRelated[$i] + 1;
}
}
$arResult[$i] = $curKey;
}
return $arResult;
}
}
$arr = range(0, 4);
$count = count($arr);
foreach($arr as $key => $v)
{
if($arRelated = array_neighbor($count, $key, $arRelated))
{
$arHeighbor[$key]['RELATED'] = $arRelated;
}
}
echo '<pre>';print_r($arHeighbor); echo '</pre>';
?>
数组
(
[0] => 数组
(
[RELATED] => 数组
(
[1] => 4
[2] => 1
)
)
[1] => 数组
(
[RELATED] => 数组
(
[1] => 0
[2] => 2
)
)
[2] => 数组
(
[RELATED] => 数组
(
[1] => 1
[2] => 3
)
)
[3] => 数组
(
[RELATED] => 数组
(
[1] => 2
[2] => 4
)
)
[4] => 数组
(
[RELATED] => 数组
(
[1] => 3
[2] => 0
)
)
)
Papipo 在下面提供的函数在概念上很有用,但不起作用。
“由于您没有通过引用传递数组,因此它的指针只在函数内部移动。”
这是正确的,但是您在 has_next() 函数中操作的数组的指针将设置为第一个元素,而不是与原始数组相同的位置。您想要做的是通过引用将数组传递给 has_next() 函数。在 has_next() 函数中,创建一个数组副本进行操作。找出原始数组的当前指针位置,并将工作副本数组上的指针设置为相同的元素。然后您可以测试数组是否具有“下一个”元素。
尝试使用以下方法代替
<?php
function has_next(&$array)
{
$A_work=$array; //$A_work 是 $array 的副本,但其内部指针设置为第一个元素。
$PTR=current($array);
array_set_pointer($A_work, $PTR);
if(is_array($A_work))
{
if(next($A_work)===false)
return false;
else
return true;
}
else
return false;
}
function array_set_pointer(&$array, $value)
{
reset($array);
while($val=current($array))
{
if($val==$value)
break;
next($array);
}
}
?>
PHP:5.2.10-2ubuntu6.3(实际情况下的默认 apt-get 安装,参见日期,jaunty 9.10 Ubuntu 发行版 - G33kWoRDs)
如果您复制数组,请查看您的数组指针 - 指针也会被复制。
例如,如果您有以下结构
<?php
$array = array('zero','one','two','three','four','five','six','seven');
$array2 = $array;
next($array);
echo key($array);
echo key($array2);
// 将输出:
// 1
// 0
?>
但是,如果您在设置指针后复制数组,指针也会被复制
<?php
$array = array('zero','one','two','three','four','five','six','seven');
next($array);
$array2 = $array;
echo key($array);
echo key($array2);
// 将输出:
// 1
// 1
?>
更重要的是,foreach 在遍历后不会重置指针
<?php
$array = array('zero','one','two','three','four','five','six','seven');
next($array);
$array2 = array();
foreach($array AS $key => $value){
echo $key;
$array2[$key] = $value;
}
echo var_dump(key($array));
echo key($array2);
// foreach 将输出:
// 0 1 2 3 4 5 6 7
// 键将输出:
// NULL
// 0
?>
PHP 函数似乎在遍历后会将指针重置到给定位置(我不知道内部处理 - 也可能使用了数组的副本)
<?php
$array = array('zero','one','two','three','four','five','six','seven');
next($array);
$array2 = array_values($array);
echo key($array);
echo key($array2);
// 将输出:
// 1
// 0
?>
有很多方法,例如 array_merge($array),既不会重置 $array 的指针,也不会将指针复制到 $array2。请注意这一点。
希望这能有所帮助。
使用 foreach 替换使用 reset()/next() 的代码时要小心,因为 foreach 不会更新数组的内部指针。这意味着您不能,例如,在 foreach 循环中使用 next() 跳过元素,或者在函数内使用 current() 获取对当前元素的引用。您可能依赖此内部指针的代码,替换它将比您预期的工作更多。
参见 https://php.net/foreach
我建议在文档主体顶部包含一个警告,说明不应在 foreach 循环中使用 next()。曾经,它似乎在那里,但我花了数小时试图解决这种组合导致的奇怪问题,结果在另一个网站上偶然发现了一个线索,这似乎表明它最初被清楚地标识出来。如果您仔细查找,此问题会在某些说明中提到,但人们不会期望在那里查找如此基本的内容。
我需要知道数组是否还有更多项,但无需移动数组的内部指针。也就是说,一个 has_next() 函数
<?php
函数 has_next($array) {
if (is_array($array)) {
if (next($array) === false) {
return false;
} else {
return true;
}
} else {
return false;
}
}
$array = array('fruit', 'melon');
if (has_next($array)) {
echo next($array);
}
// 输出 'melon'
?>
由于您没有通过引用传递数组,因此它的指针只在函数内部移动。
希望对您有所帮助。
papipo 的 has_next 函数更易读的版本
<?php
function has_next($array) {
$has_next = is_array($array) && next($array) !== false;
return $has_next;
}
?>
或者
<?php
function has_next($array) {
$has_next = false;
if(is_array($array)) {
$has_next = next($array) !== false;
}
return $has_next;
}
?>
这是一个很好的例子,说明如何使用 php key() 手册中的 current() 和 next() 函数遍历数组。在我看来,这个具体的例子最好放在 current() 和 next() 手册中,而不是 key() 手册中。
<?php
$array = array(
'fruit1' => 'apple',
'fruit2' => 'orange',
'fruit3' => 'grape',
'fruit4' => 'apple',
'fruit5' => 'apple');
// 此循环输出所有关联数组
// 值等于 "apple" 的键
reset($array); // 为循环准备数组
while ($fruit_name = current($array)) {
if ($fruit_name == 'apple') {
echo key($array), "\n";
}
next($array);
}
?>
注意!使用 next() 和 prev() 可能丢失数组指针。
<?php
// 例子
$array = array(
'fruit1' => 'apple',
'fruit2' => 'orange',
'fruit3' => 'grape',
'fruit4' => 'apple',
'fruit5' => 'apple');
reset($array); // 准备数组
$row = current($array);
var_dump($row); // 'apple'
$row = prev($array);
var_dump($row); // false. 数组指针丢失!
$row = next($array); // 无法返回到之前的(第一个/最后一个元素)!
var_dump($row); // false
?>
这是在循环中使用 next 的最佳示例
<?php
$array = array(
'fruit1' => 'apple',
'fruit2' => 'orange',
'fruit3' => 'grape',
'fruit4' => 'apple',
'fruit5' => 'apple');
// 此循环输出所有关联数组
// 值等于 "apple" 的键
reset($array); // 为循环准备数组
while ($fruit_name = current($array)) {
if ($fruit_name == 'apple') {
echo key($array), "\n";
}
next($array);
}
reset($array);
?>
此函数将返回关联数组中数组条目之前的、下一个相邻元素。如果指定的 $key 指向数组的最后一个或第一个元素,则将连续返回数组的第一个或最后一个键。这是前面发布的同一函数的改进版本。
<?php
function array_neighbor($arr, $key)
{
$keys = array_keys($arr);
$keyIndexes = array_flip($keys);
$return = array();
if (isset($keys[$keyIndexes[$key]-1])) {
$return[] = $keys[$keyIndexes[$key]-1];
}
else {
$return[] = $keys[sizeof($keys)-1];
}
if (isset($keys[$keyIndexes[$key]+1])) {
$return[] = $keys[$keyIndexes[$key]+1];
}
else {
$return[] = $keys[0];
}
return $return;
}
?>
此函数返回数组中您键后面的下一个元素,如果它是最后一个或键不存在于数组中,则返回 false。
<?php
function nextElement(array $array, $currentKey)
{
if (!isset($array[$currentKey])) {
return false;
}
$nextElement = false;
foreach ($array as $key => $item) {
$nextElement = next($array);
if ($key == $currentKey) {
break;
}
}
return $nextElement;
}
此类实现对数组的简单操作
<?php
class Steps {
private $all;
private $count;
private $curr;
public function __construct () {
$this->count = 0;
}
public function add ($step) {
$this->count++;
$this->all[$this->count] = $step;
}
public function setCurrent ($step) {
reset($this->all);
for ($i=1; $i<=$this->count; $i++) {
if ($this->all[$i]==$step) break;
next($this->all);
}
$this->curr = current($this->all);
}
public function getCurrent () {
return $this->curr;
}
public function getNext () {
self::setCurrent($this->curr);
return next($this->all);
}
}
?>
使用示例
<?php
$steps = new Steps();
$steps->add('one');
$steps->add('two');
$steps->add('three');
$steps->setCurrent('one');
echo $steps->getCurrent()."<br />";
echo $steps->getNext()."<br />";
$steps->setCurrent('two');
echo $steps->getCurrent()."<br />";
echo $steps->getNext()."<br />";
?>
关于使用foreach的引用,您可以直接使用它们。无需各种提供多行“变通方法”的帖子。
$array = array(1,2,3,4,5);
foreach($array as &$value)
或者使用$key
foreach($array as $key => $value)
{
$array[$key] = '...';
}
brentimus的`array_set_pointer`函数只有在数组值在数组中唯一且没有数组值为FALSE时才有效。使用`key()`代替`current()`会更可靠。出于类似原因,最好在调用`next()`之后检查`key()`以确定`next()`元素是否存在。例如,当查看数组的第一个元素时,仅仅检查`next()`返回的值会产生假阴性:['one', 0, 'three']
但是,事实证明,复制的数组保留了原始数组的指针,因此这里实际上不需要`array_set_pointer`。以下代码应该有效:
<?php
function has_next(array &$array) {
$A_work = $array; // $A_work是$array的一个副本,包括其内部指针。
next($A_work);
if (key($A_work) === NULL)
return false;
else
return true;
}
?>
在处理`next()`会在数组中没有更多元素或元素本身为FALSE时返回FALSE的事实后,我终于找到了一种实现`has_next()`方法的方法,它永远不会失败。您可以忽略和/或点踩我的上一条评论,它将被删除。
这是有效的代码:
<?php
function has_next(array $a){
return next($a) !== false ?: each($a) !== false;
}
?>