如何找到现有数组的下一个数字索引?

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 - 在全局命名空间中复制数组并没有为我重置下一个索引,而在函数中执行此操作(如建议的那样),确实如此。跨度>

以上是关于如何找到现有数组的下一个数字索引?的主要内容,如果未能解决你的问题,请参考以下文章

在数据框中,找到列的每个元素的下一个较小值的索引

如何在数组中找到最小值,不包括第一个索引

需要找到数组中每个元素的下一个更大的元素[重复]

将 Oracle 序列重置为现有列中的下一个值的最佳方法?

数组中的下一个和索引超出范围

如何找到最接近某个数字的数组元素? [复制]