Может ли кто-нибудь помочь мне с некоторым кодом или инструкциями о том, как пройти рекурсивно массив и при достижении последнего элемента распечатать полный путь к нему? Простое эхо будет работать, потому что я буду адаптировать код к некоторой другой функции, которую я разрабатываю.
Функция не должна указывать размерность массива, потому что этот параметр будет передан:
Пример:
$depth = 8; $array[1][3][5][6][9][5][8][9];
Когда функция достигает 8-го элемента, он печатает весь путь к ней:
//print path '1 -> 3 -> 5 -> 6 -> 9 -> 5 -> 8 -> 9'
Как я сказал, только печать в этом формате будет работать, потому что я буду внедрять код в какую-то другую функцию.
ключи массива могут иметь одинаковое значение. Очевидно, что одно и то же значение в той же последовательности для всего арари.
Обновлено:
Прогулка рекурсивно функционирует:
$someArray[1][2][3] = 'end'; $someArray[1][2][6] = 'end'; $someArray[1][3][6] = 'end'; $someArray[4][3][7] = 'end'; function listArrayRecursive(&$array_name, $ident = 0){ if (is_array($array_name)){ foreach ($array_name as $k => &$v){ if (is_array($v)){ for ($i=0; $i < $ident * 10; $i++){ echo " "; } echo $k . " : " . "<br>"; listArrayRecursive($v, $ident + 1); }else{ for ($i=0; $i < $ident * 10; $i++){ echo " "; } echo $k . " : " . $v . "<br>"; } } }else{ echo "Variable = " . $array_name; } } listArrayRecursive($someArray);
Будет печать:
1 : 2 : 3 : end 6 : end 3 : 6 : end 4 : 3 : 7 : end
Теперь, как я могу также печатать путь массива каждый раз, когда он достигает конца? Например:
1 : 2 : 3 : end : path -> 1,2,3 6 : end : path -> 1,2,6 3 : 6 : end : path -> 1,3,6 4 : 3 : 7 : end : path -> 4,3,7
EDITED CODE, ДОБАВЛЯЮЩИЙ ТРЕТИЙ ПАРАМ ДЛЯ ЗАПИСИ ПУТЬ:
$someArray[1][2][3] = 'end'; $someArray[1][2][6] = 'end'; $someArray[1][3][6] = 'end'; $someArray[4][3][7] = 'end'; $someArray[3][2] = 'end'; function listArrayRecursive(&$array_name, $ident = 0, $path = null){ foreach ($array_name as $k => &$v){ if (is_array($v)){ for ($i=0; $i < $ident * 10; $i++){ echo " "; } echo $k . " : " . "<br>"; $path .= $k . ', '; listArrayRecursive($v, $ident + 1, $path); }else{ for ($i=0; $i < $ident * 10; $i++){ echo " "; } echo $k . " : " . $v . ' - path -> ' . $path . "<br>"; } } } listArrayRecursive($someArray);
Будет печать:
1 : 2 : 3 : end - path -> 1, 2, 6 : end - path -> 1, 2, 3 : 6 : end - path -> 1, 2, 3, 4 : 3 : 7 : end - path -> 1, 4, 3, 3 : 2 : end - path -> 1, 4, 3,
Вы можете использовать RecursiveIteratorIterator
( docs ), чтобы выполнить сложную работу по рекурсии через массивы.
function listArrayRecursive($someArray) { $iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($someArray), RecursiveIteratorIterator::SELF_FIRST); foreach ($iterator as $k => $v) { $indent = str_repeat(' ', 10 * $iterator->getDepth()); // Not at end: show key only if ($iterator->hasChildren()) { echo "$indent$k :<br>"; // At end: show key, value and path } else { for ($p = array(), $i = 0, $z = $iterator->getDepth(); $i <= $z; $i++) { $p[] = $iterator->getSubIterator($i)->key(); } $path = implode(',', $p); echo "$indent$k : $v : path -> $path<br>"; } } }
Этот пример – дать вам идею, а не решать настоящую задачу.
function recursiveSearch($array,$search){ foreach($array as $key=>$val){ if($val==$search)return $key; $x=recursiveSearch($array[$key],$search); if($x)return $key.' -> '.$x; } } echo recursiveSearch($array,'search');
Если совпадение не найдено, возвращается null.
$a= array(1,2,3,4,5,6); $val = end($a); print_array($a,$val); function print_array(&$arr, $val) { if ($val === false) return; $curr = prev($arr); print_array($arr,$curr); echo $val; }
Я просто написал функцию, которая делает рекурсивный цикл немного проще: подобно array_walk_recursive, но с некоторыми дополнительными функциями
public static function walk($array, $callback, $custom = null, $recursive = false, $info = []) { $r = $recursive; if (gettype($r) === 'integer') { $r--; } $info['depth'] = empty($info)?1:$info['depth'] + 1; $info['count'] = count($array); $info['i'] = 1; foreach($array as $k => $v) { if (is_array($v) && $r > 0) { $array[$k] = static::walk($v, $callback, $custom, $r, $info); } else { $array[$k] = $callback($v, $k, $custom, $info); } $info['i'] ++; } return $array; } public static function walkable($v, $k, $custom, $info) { if (is_string($v)) { return $v." [ custom: {$custom['key']} ] [ level: ".$info['depth'].' | No '.$info['i'].' of '.$info['count']." ]"; } return $v; }
Вызывается так:
$result = Namespace\ClassName::walk($array, ['Namespace\ClassName', 'walkable'], ['key'=>'value'], true);
Установка рекурсивного значения на false будет оценивать только первый уровень.
Установка рекурсивного значения в true приведет к обходу всего массива.
Установка рекурсивного значения в целое число приведет к тому, что он будет переходить только на эту глубину.
Доступные функции могут ссылаться или передаваться на обратный вызов как анонимная функция.
(ожидается: значение, ключ, обычай, информация) Возвращаемое значение заменяет текущее значение.
Пользовательские данные могут быть переданы, а дополнительная информация предоставлена вам.
Вы можете расширить функцию ходьбы, если вам нужна дополнительная информация.
У меня была схожая проблема. Здесь находится решение «Глубино-первое поиск» (без глубины пути, оно доходит до самого конца массива). Прокомментируйте инструкцию if, если вы не хотите включать значение:
$output = array(); retrievePath($someArray, $output); function retrievePath($someArray, array &$pathKeeper) { if(!is_array($someArray)){ // $someArray == "end" $element = array_pop($pathKeeper) ?? '';// if the array is empty pop returns null, we don't want that array_push($pathKeeper, $element . '->'. $someArray); } else{ end($someArray);//we want to get the last element from the array so we move the internal pointer to it's end $endElKey = key($someArray);//take the key where the pointer is reset($someArray); foreach($someArray as $key=>$value){ $element = array_pop($pathKeeper); array_push($pathKeeper, $element === null ? $key : $element . '->' . $key);// we don't want '->' at the beginning retrievePath($value, $pathKeeper); if($key != $endElKey) //we check whether this is not the last loop array_push($pathKeeper, $element); } } }
<?php function printListRecursive($a, $var='', $i = 0) { if (!is_array($a)) { $var .= $a; return $var; } $string = ""; foreach ($a as $k => $value) { $string .= str_repeat(" ", $i) .' - '. $k . ':'; if (!is_array($value)) { $string .= $value . '<br />'; } else { $string .= '<br />'; $string .= printListRecursive($value, $var, $i + 1); } } return $string; } $test_array = [ 'America' => [ 'Argentina' => 'Buenos Aires', 'Peru' => 'Lima' ], 'Europe' => [ 'Ireland' => 'Dublin', 'France' => 'Paris', 'Italy' => 'Rome' ] ]; $result = printListRecursive($test_array); echo $result; ?>
Проверить код здесь
Вы можете добавить третий параметр, который содержит фактический путь как String. В конце вы можете его вывести.