如何在php数组中找到"needle"的最后一次出现?

6

有一个内置函数用于查找值对应的数组键 - array_search。但是,如示例所示,此函数仅找到第一个匹配项,而我需要最后一个:

<?php
$array = array(0 => 'blue', 1 => 'red', 2 => 'green', 3 => 'red');

$key = array_search('green', $array); // $key = 2;
$key = array_search('red', $array);   // $key = 1;
?>

这方面有没有内置函数呢?
如果没有,我可以反向使用 foreach 吗(从最后一个键到第一个键)?

如果所有的答案都是否定的,我想这是唯一的解决方案:

function array_search_last($needle, $array, $strict = false) {
    $keys = array_keys($array);
    //Not sure how smart PHP is, so I'm trying to avoid IF for every iteration
    if($strict) {
      for($i=count($keys)-1; $i>=0; $i--) {
        //strict search
        if($array[$keys[$i]]===$needle)
          return $keys[$i];
      } 
    }
    else {
      for($i=count($keys)-1; $i>=0; $i--) {
        //benevolent search
        if($array[$keys[$i]]==$needle)
          return $keys[$i];
      } 
    }
}

我希望有更好的选择。

array_reverse() - Mark Baker
那有多快?我可以算出来,但我希望脚本能够有效。 - Tomáš Zato
1
为什么不对其进行基准测试,告诉我们哪个更有效? - user557846
3个回答

12

但他们所有人都忽略了一件事,这会导致OP所需的结果不正确,他正在寻找最后一个元素的索引,并且反转数组将导致重新索引键(当为数字时),因此最终解决方案是将preserve_keys参数设置为TRUE 查看文档

$array = array(0 => 'blue', 1 => 'red', 2 => 'green', 3 => 'red');

$reversed = array_reverse($array, true);

echo array_search('red', $reversed);
// outs 3

9
array_search('green', array_reverse($array));

先反转它,再进行搜索。

1
取决于您的数组有多大。由于它返回一个新数组,我相信您会拥有原始数组的副本,因此数据会增加一倍。但如果它是一个相对较小的数组,我不会担心进行预优化。如果您的应用程序受到最可能是微秒差异的影响,那么您可能正在使用错误的语言。 - Lee
我正在解析某个网站的相当大的XML源。足够大,以至于打开时会使浏览器崩溃。我将使用此函数来检查我在XML树中的当前位置 - 脚本将逐步缓慢地解析文件。 - Tomáš Zato
我猜你的意思是脚本会发现它在 XML 中崩溃之前的位置?如果是这样,你应该用不同的方式来解决问题。你可以通过命令行运行 PHP,这样就可以避免浏览器超时。只要将时间限制设置为无限,理论上你可以运行你的脚本数年而不会因解析时间而“崩溃”。我还会考虑将任务分成几个较小的任务。我真的会想办法编写代码,使其不会崩溃,而不是试图处理崩溃。 - Lee
所有的东西都在由我的客户支付的 Web 托管上运行。在当前程序中,限制是标准的 30 秒。虽然脚本实际上不会崩溃。它通过 XML(使用文件函数)并在每个有趣的条目上使用标准的 XML 解析器,而不是整个文件。当时间到了,它保存偏移量和其他信息并退出。我在解析时不急,所以我更喜欢在晚上进行适当的间隔。 - Tomáš Zato
1
array_keys会占用更多的内存(这只是一种假设,可能有趣的是进行测量)。原因:PHP使用引用计数的写时复制技术来处理变量,但对于键来说这种方法不起作用。使用array_keys()函数时,它必须为每个元素创建新的变量(加上保存它们的哈希表),而使用array_reverse()函数时,它可以重用值对象并简单地增加引用计数(除非它们是引用,那么需要复制...)并将它们放入一个新的哈希表中。 - johannes
显示剩余2条评论

0

这里有一个更通用的解决方案,适用于多维关联数组。它可以找到特定列的所有匹配值:

$needle = array(0 => 'name_2');

$haystack = array(
    23    => array(
        'id' => '23',
        'name' => 'name_1'
    ),
    'arr' => array(
        'id' => 'arr',
        'name' => 'name_2'
    ),
    'arrss' => array(
        'id' => 'arrss',
        'name' => 'name_2'
    )
);

$haystack_name = array_column($haystack, 'name', 'id');
// array(
//      '23' => 'name_1',
//      'arr' => 'name_2'
//      'arrss' => 'name_2'
// )

$name_matches = array_intersect($haystack_name, $needle);
// array(
//      'arr' => 'name_2'
//      'arrss' => 'name_2'
// )

$matches = array_intersect_key($haystack, $name_matches);
// array(
//     'arr' => array(
//         'id' => 'arr',
//         'name' => 'name_2'
//     ),
//     'arrss' => array(
//         'id' => 'arrss',
//         'name' => 'name_2'
//     )
// )

$last_value = $matches[count($matches) - 1];
// array(
//      'id' => 'arrss',
//      'name' => 'name_2'
//     )

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