Since "data structure" is very vague, and your only hint is that you're using PHP, I will assume that your "data structure" means the following:
[
'USA' =>
[
'Alabama' =>
[
'Montgomery',
'Birmingham'
],
'Arizona' =>
[
'Phoenix',
'Mesa',
'Gilbert'
]
],
'Germany' =>
[
'West Germany' =>
[
'Bonn',
'Cologne'
]
]
]
And I assume that you want your result in the form
['USA', 'Alabama', 'Birmingham']
If this is not the case, please inform us about how your data is actually available and how you want your result.
Is there in PHP simple way to search in such structures?
That depends on your definition of "simple".
For me, a solution that fits into a single function is "simple".
However, there is no out-of-the-box solution for this that you can use in a one-liner.
If you only need to find the "leafs", you could use a RecursiveIteratorIterator
over a RecursiveArrayIterator
as in this StackOverflow question.
But since you need to find intermediary keys too, that it not really an option.
The same goes for array_walk_recursive
.
You could probably use ArrayIterator
or array_walk
, but in this example they can't really do anything a foreach
loop can't, besides complicate things.
So I'd just go with a foreach
loop:
function findMyThing($needle, $haystack) // Keep argument order from PHP array functions
{
// We need to set up a stack array + a while loop to avoid recursive functions for those are evil.
// Recursive functions would also complicate things further in regard of returning.
$stack =
[
[
'prefix' => [],
'value' => $haystack
]
];
// As long as there's still something there, don't stop
while(count($stack) > 0)
{
// Copy the current stack and create a new, empty one
$currentStack = $stack;
$stack = [];
// Work the stack
for($i = 0; $i < count($currentStack); $i++)
{
// Iterate over the actual array
foreach($currentStack[$i]['value'] as $key => $value)
{
// If the value is an array, then
// 1. the key is a string (so we need to match against it)
// 2. we might have to go deeper
if(is_array($value))
{
// We need to build the current prefix list regardless of what we're gonna do below
$prefix = $currentStack[$i]['prefix'];
$prefix[] = $key;
// If the current key, is the one we're looking for, heureka!
if($key == $needle)
{
return $prefix;
}
// Otherwise, push prefix & value onto the stack for the next loop to pick up
else
{
$stack[] =
[
'prefix' => $prefix,
'value' => $value
];
}
}
// If the value is NOT an array, then
// 1. the key is an integer, so we DO NOT want to match against it
// 2. we need to match against the value itself
elseif($value == $needle)
{
// This time append $value, not $key
$prefix = $currentStack[$i]['prefix'];
$prefix[] = $value;
return $prefix;
}
}
}
}
// At this point we searched the entire array and didn't find anything, so we return an empty array
return [];
}
Then just use it like
$path = findMyThing('Alabama', $array);