Skip to content
Theory · Array functions · lesson 5 of 8

Searching an array

The attendant can do more than sort and pick out items: they can also find them. Ask "Do you have a blue coat?", and they answer "yes" or "no". Ask "Which hook is it on?", and they name a number.

In PHP the first question is answered by the in_array function, the second by array_search.

As you already know, the == operator compares loosely: to it the string '10' and the number 10 are the same. Both functions compare exactly that way by default:

PHP
<?php

$allowed = ['10', '20', '30'];
var_dump(in_array(10, $allowed)); // bool(true)
var_dump(in_array(10, $allowed, true)); // bool(false)
var_dump(in_array('10', $allowed, true)); // bool(true)

Let's go through it line by line:

  1. $allowed is a list of allowed codes. They are strings: that is how data usually arrives from a form or a file.
  2. in_array(10, $allowed) compares with == and finds '10', so it returns true, and var_dump prints bool(true).
  3. With the third argument true the comparison uses ===. The number 10 is not equal to the string '10', and the answer is bool(false).
  4. The string '10' matches the string '10' under strict comparison too.

in_array: is the value there

in_array checks whether a value is among the array's values and returns true or false. It does not look at the keys.

Loose comparison by default

Without a third argument each value of the array is compared with the one you look for using ==. That is why in_array('1e1', $allowed) also returns true. Both strings, '1e1' and '10', are numeric, and == compares such strings as numbers: 1e1 is 10.

Strict comparison with true

The third argument true switches on ===: only a value of the same type matches. An allowlist is a list of allowed values: roles, codes, identifiers. When you check against one, always pass true, or the check also lets through '1e1', which is not on the list.

Interviewers often ask why in_array without a third argument is dangerous. The answer: it compares with ==, and values that are only loosely equal to the allowed ones get through the allowlist.

array_search: where the value is

array_search searches the same way as in_array and understands the same third argument. But it returns no "yes" or "no": it returns the key of the element it found. If the value is not there, it returns false:

PHP
$days = ['mon', 'tue', 'wed'];
var_dump(array_search('tue', $days)); // int(1)
var_dump(array_search('mon', $days)); // int(0)
var_dump(array_search('sun', $days)); // bool(false)

Look at the second line. 'mon' hangs on the first hook, and that hook's number is 0. It is a real key, and yet in an if condition the number 0 is falsy, as false is.

That is why the result of array_search is compared strictly: $pos === false means "not found", and any other value is the key of a match. This is another classic interview question: "What is dangerous about if (array_search(…))?"

This is where the attendant picture falls short. A real attendant asked "where is the coat?" says "on the first hook", while array_search names the number 0, and that answer can be mistaken for "nowhere".

Key or value

in_array and array_search search among the values. A key is checked by isset and array_key_exists, and the two part ways on a null value. For $stock = ['kiwi' => null] the expression isset($stock['kiwi']) gives false, while array_key_exists('kiwi', $stock) gives true: the key is there, it holds null.

Five more helpers

PHP has ready answers to common questions about an array:

PHP
$visits = [3, 7, 3, 5, 7];
echo implode(' ', array_unique($visits)), "\n"; // 3 7 5
echo json_encode(array_unique($visits)), "\n"; // {"0":3,"1":7,"3":5}
echo max($visits), ' ', min($visits), "\n"; // 7 3
echo implode(' ', range(1, 5)), "\n"; // 1 2 3 4 5
echo array_key_first(['pear' => 7, 'kiwi' => 9]), "\n"; // pear
  • array_unique removes repeats and keeps the first occurrence of each value together with its key. So, as after array_filter, the numbering is left with holes.
  • max and min return the largest and the smallest value.
  • range(1, 5) builds a list of the numbers from 1 to 5 inclusive.
  • array_key_first returns the array's first key, and null for an empty array.

Common mistake

The result of array_search was checked with a plain condition:

PHP
$queue = ['ann', 'bob', 'cat'];
$pos = array_search('ann', $queue);
if (!$pos) { // ✗
    echo 'not in the queue', "\n";
}

The program prints not in the queue, although 'ann' is first in the queue, and PHP shows no message. array_search returned the key 0, and !0 is true. The fix is a strict check: if ($pos === false).

Key points

  • in_array and array_search compare with == by default; the third argument true switches on ===.
  • in_array answers true or false, while array_search returns the key of the element it found, or false.
  • The key 0 is a real match, but it is falsy in an if, so the result of array_search is checked with === false.
  • array_unique, max, min, range and array_key_first answer common questions about an array in one line.