现在从 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 | 对 object 调用此函数已弃用。可以先使用 get_mangled_object_vars() 将 object 转换为 array,或者使用实现 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....
}
此函数将在关联数组中返回数组条目的前一个和下一个邻居。如果指定的 $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>';
?>
Array
(
[0] => Array
(
['RELATED'] => Array
(
[1] => 4
[2] => 1
)
)
[1] => Array
(
['RELATED'] => Array
(
[1] => 0
[2] => 2
)
)
[2] => Array
(
['RELATED'] => Array
(
[1] => 1
[2] => 3
)
)
[3] => Array
(
['RELATED'] => Array
(
[1] => 2
[2] => 4
)
)
[4] => Array
(
['RELATED'] => Array
(
[1] => 3
[2] => 0
)
)
)
这段代码返回指定键的邻居。如果它没有邻居,结果将为空。我的方法是使用键的顺序来确定邻居,这与仅仅获取数组中的下一个/上一个元素不同。随意指出愚蠢的地方 :)
<?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;
}
?>
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。请看下面的例子。
希望这能帮到你。
使用 reset()/next() 替换使用 foreach 的代码时要小心,因为 foreach 不会更新数组的内部指针。这意味着你不能,比如说,使用 next() 在 foreach 循环中跳过一个元素,或者使用 current() 在函数中获取对当前元素的引用。你可能有一些代码依赖于这个内部指针,替换它将比你预期的工作量更大。
请查看 https://php.net/foreach
我需要知道一个数组是否有更多项,但无需移动数组的内部指针。也就是说,一个 has_next() 函数。
<?php
function 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;
}
?>
这可能很方便,我不知道该在哪里发布它。我需要一个简单的函数来循环遍历一个数组。我最终把它做成了一个类,这样我就可以拥有多个循环。如果您喜欢它或发现它有用,请给我发邮件告诉我。
class Cycle
{
var $position;
var $dataArray;
var $dataArrayCount;
function Cycle()
{
$this->dataArray = func_get_args();
$this->dataArrayCount = count($this->dataArray);
}
function Display()
{
$this->position = (!isset($this->position) || $this->position >= ($this->dataArrayCount - 1)) ? 0 : $this->position += 1;
return $this->dataArray[$this->position];
}
}
$bgColor = new Cycle('#000000', '#FFFFFF', '#FF0000');
echo $bgcolor->Display();
// 返回 #000000
echo $bgcolor->Display();
// 返回 #FFFFFF
echo $bgcolor->Display();
// 返回 #FF0000
echo $bgcolor->Display();
// 返回 #000000