'Search for array row with specific column value and return another value from qualifying row

I have a multidimensional array that I am trying to search for a specific value (url) and then retrieve an another value in the same row (value). I also need to divert to an else if it is not found.

array(2) { 
  [0]=> array(2) { 
    ["url"]=> string(7) "fareham" 
    ["value"]=> string(7) "Fareham" 
  } 
  
 [1]=> array(2) { 
    ["url"]=> string(11) "southampton" 
    ["value"]=> string(11) "Southampton" 
  } 
}

I have been experimenting with array_key_exists() and isset() to check it's set and just coming up null!

For example, if I search for fareham, I want to return Fareham. If I search for nottingham, I expect null.

How can I isolate the qualifying value?



Solution 1:[1]

Use array_column() to index the data by the url columns and then use isset() to check if the value is there...

$data = array_column($data, "value", "url");
$search = 'southampton';

$value = isset($data[$search])?$data[$search]:"not found";

echo $value;

or for PHP 7+, you can use the null coalescing operator (??)

$value = $data[$search]??"not found";

Solution 2:[2]

Here is the minimal way to do it (no checks)

$a = array (
    0 => 
    array (
        "url" => 'fareham',
        "value" => 'Fareham'
    ),
    1 => 
    array (
        "url" => 'southampton',
        "value" => 'Southampton'
    )
);

$u = 'fareham';
$i = $a[false===($f=array_search($u,array_column($a,'url')))?-1:$f]['value'];
print_r($i);

Output

Fareham

Sandbox

How it works

First we create an array we can search by using array_column on the column we want to search in this case url. It looks like this [0=>'fareham', 1=>'southampton']

Then we use the normal array_search which returns an index, if you notice above the indexes are correlated to the original array. Which means we can put that in as the top level key, then it's a simple matter of adding the key we want.

Because array_search can return a boolean(false) which PHP sees as 0 or the first index I put a little hack in for that. But a better way is to check it like this: $a = array ( 0 => array ( "url" => 'fareham', "value" => 'Fareham', "extra" => 'Foo' ), 1 => array ( "url" => 'southampton', "value" => 'Southampton', "extra" => 'Bar' ) );

function serchMultiDimensionalValue($needle, $haystack, $fields='value'){
   if(false === ($f=array_search($needle,array_column($haystack,'url')))) return false; //or return [];

   if(!is_array($fields)) $fields = [$fields];

   return array_intersect_key($haystack[$f], array_flip($fields));
}


var_dump(serchMultiDimensionalValue('foo',$a));
var_dump(serchMultiDimensionalValue('fareham',$a));
var_dump(serchMultiDimensionalValue('fareham',$a, 'extra'));
var_dump(serchMultiDimensionalValue('fareham',$a, ['extra','url']));

Ouput

bool(false)
array(1) {
  ["value"]=>
  string(7) "Fareham"
}
array(1) {
  ["extra"]=>
  string(3) "Foo"
}
array(2) {
  ["url"]=>
  string(7) "fareham"
  ["extra"]=>
  string(3) "Foo"
}

Sandbox

I added a bit more "functionality" to it, hope you don't mind.

Solution 3:[3]

While it might be alluring to seek out a one-liner like:

array_column($array, $returnColumn, $haystackColumn)[$needle] ?? null

Be aware that array_column() will be unconditionally doubling the memory usage (because it is generating a new array with the same length as the original) for the sake of assigning new first level keys to search by.

Metaphorically speaking, it is building a new "registry" including every homeowner's name and their address -- yes, you can find out who lives there without knocking on the front door, but you had to knock ob every door to collect every home's details before enjoying this convenience. Why not just knock on the door of each original house and ask if they are who you are looking for? It is much easier, and you will be able to "quit" early as soon as you find the homeowner that you are looking for.

For best efficiency and for least memory usage, I recommend the below classic loop with conditional break. It is built with dynamic search and return variables for general usage, but you can use hardcoded values if you like.

Code: (Demo)

$array = [
    ["url" => 'fareham', "value" => 'Fareham'],
    ["url" => 'southampton', "value" => 'Southampton']
];
$needle = 'fareham';
$haystackColumn = 'url';
$returnColumn = 'value';

$value = null;
foreach ($array as $row) {
    if ($row[$haystackColumn] === $needle) {
        $value = $row[$returnColumn];
        break;
    }
}
var_export($value); // 'Fareham'

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3