Maximus Light
Maximus Light

Reputation: 431

Get keys from multidimentional array by value

I need to get all "top level" keys from multidimensional array by searching the "bottom level" values. Here is an example of the array:

$list = array (
    'person1' => array(
           'personal_id' => '1',
           'short_information' => 'string',
           'books_on_hand' => array(
                         'Book 1',
                         'Book 2',
                         'Book 3',
                        )
     ),
     'person2' => array(
           'personal_id' => '2',
           'short_information' => 'string',
           'books_on_hand' => array(
                         'Book 4',
                         'Book 2',
                         'Book 5',
                        )
     ),
     'person3' => array(
           'personal_id' => '3',
           'short_information' => 'string',
           'books_on_hand' => array(
                         'Book 4',
                         'Book 2',
                         'Book 1',
                         'Book 3',
                        )
     ),
     //etc...
);

I want to know all persons who have "Book 2" on hand. I can get that information by loop like this:

foreach ($list as $person => $info){
   $check = array_search( 'Book 2', array_column($info, 'books_on_hand') );
   if ( $check !== false ){
      $results .= 'Name: '.$person; 
      $results .= 'ID: '.$info['personal_id'];
      //get other infos other stuff, if necessary
   }
}

The problem is, that foreach in this case is very heavy on memory and only grows more when array has a thousand+ entries. It needs to run through all of the persons, even if only 3 persons at the very top of the array have "Book 2".

I have been trying to optimize it by getting persons with "Book 2" using built-in functions like array_search, array_keys, array_column and only then run foreach for persons found, but I had no luck with getting "top level" keys.

Is it possible to optimize or use built-in function to search multidimensional array?

Upvotes: 1

Views: 81

Answers (1)

AbraCadaver
AbraCadaver

Reputation: 78994

One way would be to filter it first. Now your result is structured like $list but it only contains elements with the needed book:

$find   = 'Book 2';
$result = array_filter($list, function($v) use($find) {
                                  return in_array($find, $v['books_on_hand']);  
                              });

If all you're interested in is the person key and personal_id then this:

$find   = 'Book 2';
$result = array_map(function($v) use($find) {
                       if(in_array($find, $v['books_on_hand'])) {
                           return $v['personal_id'];
                       }
                    }, $list);

Will return something like this for persons with the needed book:

Array
(
    [person1] => 1
    [person2] => 2
    [person3] => 3
)

Upvotes: 1

Related Questions