是否有一个函数可以在一次调用中检查数组键是否存在,如果存在则获取值


Is there a function to check if an array key exists, and get the value if it does, in one call?

我想避免扫描数组两次。类似于C#中的TryGetValue。

不,没有一个内置函数可以满足您的需要。然而,写一个新的并不难:

function tryGetValue($array, $key) {
    return (array_key_exists($key, $array)) ? $array[$key] : NULL;
}

示例用法:

$array = array('foo' => 'bar', 'baz', 'bak', 'bam');
var_dump(tryGetValue($array, 'foo'));   // string(3) "bar"
var_dump(tryGetValue($array, 's'));     // NULL
var_dump(tryGetValue($array, 2));       // string(3) "bam"
var_dump(tryGetValue($array, 4));       // NULL

更新

这不是推荐的做法。因为@会抑制该表达式中的所有异常。

然而,AFAIK,这是满足OP规定标准的唯一有效方法(见对问题的评论):

我希望避免出现错误/警告,并且我希望避免扫描阵列两次。

推荐的做法可以在Amit的回答中看到。

也就是说,不要"微优化";您的代码。不要那么担心";扫描阵列两次";。编写干净、健壮的代码。稍后,如果测试发现性能问题,则评估如何提高性能。

Do处理错误和意外情况(异常)。


原始答案

@jszobody在对这个问题的评论中给出了答案。扩展他的评论:

如果数组键不存在,您希望返回什么?

如果null就这么做":

@$array[$key]

("@"抑制警告。)

如果有其他内容,并且您不在数组中存储null值,因此您永远不希望返回null,则此代码变为:

@$array[$key] ?? $YourDefaultValue

除非您的设计BOTH 1)允许在数组中存储null值,否则AND 2)需要null以外的默认值。如果这两个条件都为true,则需要使用array_key_exists显式测试密钥是否存在。

检查我在3v4l上创建的这些微基准。

以下是功能。

function tryGetValue1( $array, $key, Closure $default ) {
  return array_key_exists($key, $array)
    ? $array[$key] : $default();
}
function tryGetValue2( $array, $key, Closure $default ) {
  return ($value = @$array[$key]) !== null || array_key_exists($key, $array)
    ? $value : $default();
}
function tryGetValue3( $array, $key, Closure $default ) {
  return isset($array[$key]) || array_key_exists($key, $array)
    ? $array[$key] : $default();
}
function tryGetValueNotNull1( $array, $key, Closure $default ) {
  return ($value = @$array[$key]) !== null
    ? $value : $default();
}
function tryGetValueNotNull2( $array, $key, Closure $default ) {
  return isset($array[$key])
    ? $array[$key] : $default();
}

这取决于您是否关心null,以及您使用的PHP版本。

看起来编译器试图优化isset和array_key_exists操作,至少对于小数组是这样。这可能意味着数组有自己的内部迭代器状态用于此目的和类似目的。

有趣的是,您可以将isset和array_key_exists组合在一起(请参阅tryGetValue3),有时也会脱颖而出。

这不是一个完全合适的基准测试,因为在测试数组中没有定义空的现有键。请随意扩展示例。:)