Поиск ключа в массиве, рекурсивно
private function find($needle, $haystack) {
foreach ($haystack as $name => $file) {
if ($needle == $name) {
return $file;
} else if(is_array($file)) { //is folder
return $this->find($needle, $file); //file is the new haystack
}
}
return "did not find";
}
Эй, этот метод ищет конкретный ключ в ассоциативном массиве и возвращает связанное с ним значение. Там есть проблема с рекурсией. Любая подсказка?
Ответы
Ответ 1
Может быть, это перебор, но смешно использовать RecursiveIterators:)
UPDATE: Возможно, это было слишком много, но s >= 5.6 (особенно с 7.0) я бы полностью использовал это без сомнения.
function recursiveFind(array $haystack, $needle)
{
$iterator = new RecursiveArrayIterator($haystack);
$recursive = new RecursiveIteratorIterator(
$iterator,
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($recursive as $key => $value) {
if ($key === $needle) {
return $value;
}
}
}
UPDATE: Также, с PHP 5.6, с генераторами вы можете легко перебирать все элементы, которые пропускают фильтр, а не только первый:
function recursiveFind(array $haystack, $needle)
{
$iterator = new RecursiveArrayIterator($haystack);
$recursive = new RecursiveIteratorIterator(
$iterator,
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($recursive as $key => $value) {
if ($key === $needle) {
yield $value;
}
}
}
// Usage
foreach (recursiveFind($haystack, $needle) as $value) {
// Use `$value` here
}
Ответ 2
function array_search_key( $needle_key, $array ) {
foreach($array AS $key=>$value){
if($key == $needle_key) return $value;
if(is_array($value)){
if( ($result = array_search_key($needle_key,$value)) !== false)
return $result;
}
}
return false;
}
это будет работать!
вам нужно остановить рекурсивный глубокий поиск, вернем false и затем проверить его в функции.
вы можете найти больше примеров функций (например, используя RecursiveArrayIterator и т.д.) в этой ссылке:
http://php.net/manual/en/function.array-search.php
Ответ 3
Ответ, предоставленный xPheRe, был чрезвычайно полезен, но не совсем решил проблему в моей реализации. В нашей структуре данных имеется множество вложенных ассоциативных массивов, и может быть несколько вхождений в любой заданный ключ.
Чтобы соответствовать нашим целям, мне нужно было реализовать массив держателей, который был обновлен при обходе всей структуры вместо того, чтобы возвращаться в первом матче. Настоящая работа была предоставлена другим плакатом, но я хотел сказать спасибо и поделиться последним шагом, который мне пришлось покрыть.
public function recursiveFind(array $array, $needle)
{
$iterator = new RecursiveArrayIterator($array);
$recursive = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST);
$aHitList = array();
foreach ($recursive as $key => $value) {
if ($key === $needle) {
array_push($aHitList, $value);
}
}
return $aHitList;
}
Ответ 4
попробуйте следующее:
array_walk_recursive(
$arrayToFindKey,
function($value, $key, $matchingKey){
return (strcasecmp($key, $matchingKey) == 0)? true : false;
}
, 'matchingKeyValue'
);
Ответ 5
Лучшее решение выше пропустит случай, если ключ повторяется и возвращает только первое значение, здесь я получаю все значения в массиве:
function recursiveFind(array $array, $needle) {
$iterator = new RecursiveArrayIterator($array);
$recursive = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST);
$return = [];
foreach ($recursive as $key => $value) {
if ($key === $needle) {
$return[] = $value;
}
}
return $return;
}
Ответ 6
В ответе выше используется array_walk_recursive, но эта функция не подходит для этого случая, потому что: "Любой ключ, содержащий массив, не будет передан функции". Это означает, что функция посещает только конечные узлы.
https://www.php.net/manual/en/function.array-walk-recursive.php
Моя проблема с RecursiveIteratorIterator заключается в том, что он может вызвать ошибку memory_limit для огромного глубокого массива, поскольку итератор является объектом и сгладит все ключи в памяти, чтобы выполнить цикл для него. Таким образом, решение может состоять в том, чтобы последовательно циклически проходить по каждому ключу массива... Это не лучше для производительности, но лучше для памяти:/...