在不使用循环的情况下获取数组中第N个位置的元素

18

如何在不使用循环的情况下获取特定位置数组中第 n 个元素的 keyvalue

想象一下

$postion = 3; // get array at 3rd position
$array = array(
        "A" => "Four",
        "B" => "twp",
        "C" => "three",
        "D" => "Four",
        "E" => "Five",
        "F" => "Four");


$keys = array_keys($array);
$value = array_values($array);

echo implode(array_slice($keys, $postion, 1)), PHP_EOL; // Key at 3rd posstion
echo implode(array_slice($value, $postion, 1)), PHP_EOL; // Value at n position

输出
D
Four

该方法存在的问题是:

  • 数组多次复制会导致内存使用量增加

为什么不使用循环?

  • 您必须多次获取多个位置...循环大数据集也不高效

为什么不使用数据库?

  • 是的,使用基于内存的数据库(如Redis)可以使生活更轻松,但我特别优化数组

为什么不使用SplFixedArray

  • This would have been solution but i the follow weer because am not using positive keys ( I really this is nor fair on php part)

    Fatal error: Uncaught exception 'InvalidArgumentException' 
    with message 'array must contain only positive integer keys' 
    

大数据集是什么意思:

  • 实际上,当我尝试提出这个问题在PHP中管理超大数组时,我遇到了这个问题,所以我正在考虑使用1e61e7512M内存限制

我相信像fseek这样的数组操作可以解决问题...但不确定是否存在


抱歉,我不明白。如果您需要数据容器的行为类似于有序(索引)数组,为什么首先要使用关联数组呢? - raina77ow
你为什么要使用 array_slice 而不是直接使用 $keys[$position] - jeroen
1
@raina77ow 默认情况下,该数组是关联数组。 - Baba
@jeroen 这是一个关联数组,键名未知。 - Baba
不,$keys具有数字键,你只是在之前的行中设置了它:$keys = array_keys($array);。 - jeroen
4个回答

17
假设使用 PHP 5.4,采用数组解引用:
echo $array[array_keys($array)[$position]];

在早期版本中,您需要将其分成两行:

$keys = array_keys($array);
echo $array[$keys[$position]];

如果您需要访问多个元素,使用两行方法在5.4+中也是值得的,以便只调用相对昂贵的array_keys()函数一次。此外,解引用方法假定数组中的特定位置存在,但可能不存在。将其分成多个操作可以帮助您处理该错误情况。当然,如果您不需要访问键,则可以简单地执行以下操作:
echo array_values($array)[$position];
// or
$values = array_values($array);
echo $values[$position];

编辑

ArrayIterator 类也可以为您完成此操作:

$iterator = new ArrayIterator($array);
$iterator->seek($position);

echo $iterator->key(), " = ", $iterator->current(); // D = Four

这可能是最便宜的方法,假设在执行此操作时不会在内存中创建数组的副本(仍在研究此元素),并且对于任意键的多次访问可能是最佳方法。

2
我猜OP的问题在于,在他的情况下,array_keys太耗费资源了 - 例如当一个数组包含数百万个项目时。然而,我并不完全理解所有这些的用例:你很少需要在代码中处理大量的项目,而不是在数据库中进行操作。 - raina77ow
@raina77ow 已经更新为使用 ArrayIterator,但我不确定这是否会在底层创建一个副本,如果是这样的话,您可能失去了任何提升。 - DaveRandom
@DaveRandom,我仍然认为你作弊了……即使ArrayObject也没有seek……不错。 - Baba

6

你所希望的不可能实现。PHP的数组通过键名能够高效地进行访问,但是对于偏移量的访问却没有那么高效。数组的顺序只能以链表的形式得到,因此最好的效率只能达到O(n)级别,也就是遍历整个数组并查找偏移量:

$i = 0;
foreach ($array as $value) {
    if ($i++ === $offset) {
        // found value
    }
}

如果您想让此操作更快,那么您需要使用适当的、按数字和顺序索引的数组。

@DaveRandom 嗯...那么https://dev59.com/Wmkw5IYBdhLWcg3wNX32#10058358(和它的第一条评论)呢? - raina77ow
@raina77ow 更多证据 https://dev59.com/fWUq5IYBdhLWcg3wC79Q - Baba
2
@raina77ow 我必须诚实地说,我更倾向于选择PHP核心开发人员,他在核心代码中有与foreach相关的提交记录;-) - DaveRandom
@DaveRandom 我明白了。不过,我承认,在这种特殊情况下,我仍然看不出foreach为什么会更低效:难道refcount === 1 => no copying的规则不应该适用于这里的$array吗? - raina77ow

3

事实上,您不需要 $values 数组:

$keys = array_keys($array);

$value_3=$array[$keys[3]];

0

我不太明白你的问题,但如果你需要从位置获取键和元素

$position = 3; // get array at 3rd position
$array = array(
        "A" => "Four",
        "B" => "twp",
        "C" => "three",
        "D" => "Four",
        "E" => "Five",
        "F" => "Four");


$keys = array_keys($array);
$values = array_values($array);

if($values[$position] == "Four" && $keys[$position] == "D") {
    echo "All it's Right!\n";
}

you dont need implode for that task


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接