如何找到现有数组的下一个数字索引?
Posted
技术标签:
【中文标题】如何找到现有数组的下一个数字索引?【英文标题】:How to find the next numeric index of an existing array? 【发布时间】:2011-04-11 13:19:57 【问题描述】:我正在寻找一种简单的方法来获取数组的下一个数字索引,以获取 php 也会选择的新元素。
示例 1:
$array = array();
$array[] = 'new index';
在这种情况下,这将是 0。
示例 1a:
$array = array(100 => 'prefill 1');
unset($x[100]);
$x[] = 'new index';
对于这种情况,这将是 101。
示例 2:
$array = array(-2 => 'prefill 1' );
$array[] = 'new index';
在这种情况下,这将再次为 0。
示例 3:
$array = array(-2 => 'prefill 1', 1 => 'prefill 2' );
$array[] = 'new index';
对于这种情况,这将是 2。
我现在想知道 PHP 会为数组中的新元素选择的下一个数字键,但如果可能的话,不会遍历所有数组值。
如果添加了新元素而没有指定偏移量,我需要通过 SPL 实现自己的数组来模拟 PHP 默认行为。
示例 4:
$array = array(-2 => 'prefill 1', 'str-key-1' => 'prefill 2', 1 => 'prefill 3' , 'str-key-2' => 'prefill 4');
$array[] = 'new index';
对于这种情况,这将再次为 2。
示例 5:
$array = array(-2 => 'prefill-1', 'str-key-1' => 'prefill-2', 1 => 'prefill-3' , '5667 str-key-2' => 'prefill-4');
$array[] = 'new index';
对于这种情况,这也是 2。
更新:我添加了更多示例来展示一些极端情况。
【问题讨论】:
请注意,如果不知道数组的历史,这是不可能准确地做到的。 (见我的回答。)这有关系吗? 是的,这很重要,正如您回答的那样,从技术上讲,这个问题在 PHP 用户空间中是无法解决的,因为没有允许访问->nNextFreeElement
的辅助函数或数据结构。获得它的唯一方法是添加一个元素,然后从添加的元素中读出值。所以这是访问该属性的一种方式,但它也意味着修改数组。
【参考方案1】:
方法一:
使用end
将数组推进到末尾。获取该项目的key
。最后,将其加 1 以获取下一项的索引。像这样:
$array [ ] = 'I';
$array [4] = 'Like';
$array [ ] = 'Turtles';
end($array);
$last = key($array);
$nextindex = $last + 1;
echo $nextindex;
这个输出:
6
如果最后一个索引不是最大的或字符串(如 cmets 中所指出的),此方法会失败。所以,在这些情况下,有这个更好的方法2。
方法二:
此方法适用于基于负数和字符串的索引:
你可以得到 array_keys
并做一个 max
,然后是 +1
。像这样:
$array = array(-2 => 'prefill 1', 'str-key-1' => 'prefill 2', 1 => 'prefill 3' , 'str-key-2' => 'prefill 4');
echo max(array_keys($array)) + 1;
这输出正确:
2
【讨论】:
错误。最后一个元素不必是索引最高的元素。设置 $a[0],然后设置 $a[-3]。根据您的方法,下一个索引将是 -2,但实际上是 1。 这确实是一个不错的方法,但它假设只使用数字键。我添加了另一个示例,该示例会为您的解决方案提供错误的值。 @Sjoerd,是的。现在为此,我添加了一个 方法 2 @hakre,方法 2 也会处理基于字符串的键。 @hakre,方法 2 正确地将答案显示为2
。看看这个:codepad.viper-7.com/0oH6o3【参考方案2】:
zend 哈希表有一个元素nNextFreeElement
,其中包含您要查找的数字。每次添加一个item,这个字段都会更新为自身的最大值和索引+1。
ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC)
...
if ((long)h >= (long)ht->nNextFreeElement)
ht->nNextFreeElement = h < LONG_MAX ? h + 1 : LONG_MAX;
...
【讨论】:
有趣。这可能也是要实施的事情。【参考方案3】:我认为必要的信息不会暴露给 PHP 脚本。考虑:
<?php
$x = array(100 => 'foo');
unset($x[100]);
$x[] = 'bar';
var_dump($x);
?>
array(1)
[101]=>
string(3) "bar"
没有办法知道 101 是下一个整数,给定看似空的数组,直到添加项目之后。
如果您是从头开始构建自己的数组类,那么您可以通过私有成员变量来跟踪下一个索引。
【讨论】:
我认为这是唯一的方法,确实。 我从许多其他好的答案中选择了这个答案,因为它用少量的代码和解释很好地描述了这个问题。非常感谢 konforce 的反馈以及其他答案,尤其是带有 end() + key() 的答案,因为这是最后添加的元素。我通过向现有数组添加一个空值解决了我的技术问题,然后获取新添加的 $offset,然后我添加了我需要添加的值。这不是一个通用的解决方案,但在这里的所有帮助下,这对我来说效果很好。我很快就会在 BSD 下发布代码。【参考方案4】:在我看来,PHP 在索引值的最大值之后采用下一个正数。
【讨论】:
【参考方案5】:如果一切都失败了,您可以简单地针对副本进行测试。
// Since PHP passes by copy, we don't even need to explicitly copy.
function get_next_key($copy)
$copy[] = 'blah';
end($copy);
return key($copy);
$key = get_next_key($array);
【讨论】:
通过修改$copy
,您将复制整个数组。这会产生 2 倍的内存成本,并且不会比简单地遍历原始数组提供更好的结果,因为副本的“下一个索引”将被重置,并且不能保证与原始数组相同。
@konforce - 在全局命名空间中复制数组并没有为我重置下一个索引,而在函数中执行此操作(如建议的那样),确实如此。跨度>
以上是关于如何找到现有数组的下一个数字索引?的主要内容,如果未能解决你的问题,请参考以下文章