richard
richard

Reputation: 12526

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

I want to avoid scanning the array twice. Something like TryGetValue in C#.

Upvotes: 3

Views: 3259

Answers (3)

ToolmakerSteve
ToolmakerSteve

Reputation: 21321

UPDATE

This is not recommended practice. Because @ suppresses all exceptions in that expression.

However, AFAIK, it is the only efficient way to meet OP's stated criteria (see comment on question):

I want to avoid errors/warnings and I want to avoid scanning the array twice.

Recommended practice can be seen in Amit's answer.

That is, don't "micro-optimize" your code. Don't be so concerned about "scanning the array twice". Write clean, robust code. Later, if testing finds a performance problem, evaluate then how to improve performance.

Do handle errors and unexpected conditions (exceptions).


ORIGINAL ANSWER

@jszobody gave an answer in a comment on the question. Expanding on his comment:

What do you want to return, if the array key doesn't exist?

If null, then one approach is "just do it":

@$array[$key]

("@" suppresses warning.)

If something else, and you don't store null values in array - so you don't ever want null to be returned - then this code becomes:

@$array[$key] ?? $YourDefaultValue

Unless your design BOTH 1) allows storing of null values in the array, AND 2) wants a default other than null. If both of these conditions are true, then you would need to explicitly test whether the key exists, using array_key_exists.

Upvotes: -1

TylerY86
TylerY86

Reputation: 3792

Check these microbenchmarks I created on 3v4l.

Here are the functions.

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();
}

It depends on if you care about null, and what version of PHP you're using.

Looks like the compilers try to optimize toward the isset and array_key_exists operations, at least for small arrays. This might imply that arrays have their own internal iterator state for this and similar purposes.

Interestingly, you can combine isset and array_key_exists (see tryGetValue3) and come out ahead sometimes.

This isn't a fully appropriate benchmark, as there are no null existing keys defined in the test array. Feel free to expand on the example. :)

Upvotes: -1

Amal Murali
Amal Murali

Reputation: 76636

No, there isn't a built-in function that does what you want. However, it's not hard to write a new one:

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

Example usage:

$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

Upvotes: 2

Related Questions