Godhaze
Godhaze

Reputation: 155

Search for a qualifying subarray in a 3d array

I have an array, what Is like this:

 $itemx=
 [
     'Weapons'=>[
          'Sword'=> [
              'ID'   => '1',
             'Name'   => 'Lurker',
             'Value'  => '12',
             'Made'   => 'Acient'
           ],

           'Shield'=> [
              'ID'   => '2',
              'Name'   => 'Obi',
              'Value'  => '22',
              'Made'   => 'Acient'
            ],

            'Warhammer'=> [
                'ID'   => '3',
               'Name'   => 'Clotch',
               'Value'  => '124',
               'Made'   => 'Acient'
             ]
     ],
     'Drinks'=>[
       'Water'=> [
          'ID'   => '4',
          'Name'   => 'Clean-water',
          'Value'  => '1',
          'Made'   => 'Acient'
        ],

        'Wine'=> [
            'ID'   => '5',
           'Name'   => 'Soff',
           'Value'  => '5',
           'Made'   => 'Acient'
         ],

         'Vodka'=> [
            'ID'   => '6',
            'Name'   => 'Laudur',
            'Value'  => '7',
            'Made'   => 'Acient'
          ]
     ]


 ];

I want to find an array from it by Name or ID, so my output should be like this.

*Search by ID=4*

 'Water'=> [
          'ID'   => '4',
          'Name'   => 'Clean-water',
          'Value'  => '1',
          'Made'   => 'Acient'
        ]

I look at other topics and found that I should use array_search

But It didn't work. I tried like this:

$arra=$itemx["Drinks"];

$key = array_search(4, array_column($arra, 'ID'));
  var_dump($arra[$key]);

It also dident work when I tried with Name as a search key.

How can I get this working?

Upvotes: 1

Views: 56

Answers (3)

mickmackusa
mickmackusa

Reputation: 47864

Your coding attempt suggests that the item category is known in advance by the developer.

From PHP8.4, array_find_key() returns the key of a qualifying value and stops iterating for best performance. Demo

$cat = 'Drinks';
$id = 4;
$key = array_find_key(
    $itemx[$cat],
    fn($row) => $row['ID'] == $id
);
if ($keyword !== null) {
    var_export([$key => $itemx[$cat][$key]]);
}

Output:

array (
  'Water' => 
  array (
    'ID' => '4',
    'Name' => 'Clean-water',
    'Value' => '1',
    'Made' => 'Acient',
  ),
)

If you don't need the 2nd level key, use array_find(). If there is no match, null is returned. Demo

$cat = 'Drinks';
$id = 4;
var_export(
    array_find(
        $itemx[$cat],
        fn($row) => $row['ID'] == $id
    )
);

Output:

array (
  'ID' => '4',
  'Name' => 'Clean-water',
  'Value' => '1',
  'Made' => 'Acient',
)

Although it becomes uglier than nested foreach loops, it is possible to nest array_find_key() calls when you don't know either of the first two level keys. Demo

$sub = null;
$id = 4;
$cat = array_find_key(
    $itemx,
    function ($set) use ($id, &$sub) {
        return ($sub = array_find_key(
            $set,
            fn($row) => $row['ID'] == $id
        )) !== null;
    }
);
var_export([$sub => $itemx[$cat][$sub]]);

If you are going to use classic nested loops and only one qualifying data set is expected, break both loops as soon as a match is found. Demo

$id = 4;
foreach ($itemx as $cat => $set) {
    foreach ($set as $sub => $row ) {
        if ($row['ID'] == $id) {
            var_export([$sub => $row]);
            break 2;
        }
    }
}

Upvotes: 0

Kyle Brown
Kyle Brown

Reputation: 21

This should probably get you what you want.

function rec($itemx,$search=4){
    foreach ($itemx as $key => $value) {
        if (is_array($value)) {
            foreach ($value as $k => $v) {
                if ($v['ID'] == $search) {
                    return $value;  
                }
            }
        }
    }
}
print_r(rec($itemx,4));

Upvotes: 2

Death-is-the-real-truth
Death-is-the-real-truth

Reputation: 72299

You can do it like below:-

$search_id = 4;
$final_array = [];
 foreach($itemx as $key=>$val){
  foreach($val as $k=>$v){
    if($v['ID'] == $search_id){
      $final_array[$k] =  $itemx[$key][$k];
    }
  }
 }
 print_r($final_array);

https://eval.in/852123

Upvotes: 2

Related Questions