У меня есть следующий (json) объект:
$obj = json_decode('{ "Group1": { "Blue": { "Round": [ "Harold", "Arthur", "Tom" ] }, "Green": { "Round": [ "Harold" ], "Circle": [ "Todd", "Mike" ] } }, "Group2": { "Blue": { "Round": [ "Peter" ] } } }', true);
Я пытаюсь понять, как рекурсивно пройти через него, чтобы я мог видеть все разные пути, которые находятся в массиве.
Это может быть 4 отдельных эха или 4 строки строки. >
Можно заменить чем-нибудь или вообще ничего. Если каждая строка была эхо-сигнал отдельно или помещена в массив, который, вероятно, даст максимальную гибкость.
Group1 - Blue - Round - (Harold, Arthur, Tom) Group1 - Green - Round - (Harold) Group1 - Green - Circle - (Todd, Mike) Group2 - Blue - Round - (Peter)
Я не могу обвести вокруг себя голову, поэтому любая помощь будет оценена по достоинству.
Я думаю, что могу как-то циклично прокручивать каждый из них:
foreach($obj as $index => $value) { // and then somehow do this until you reach an array? }
Протестировано только по данному образцу. Но это должно работать, если уровни массива увеличены. В основном я использую функции класса RecursiveIteratorIterator
// Initialize RecursiveIteratorIterator $iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($obj), RecursiveIteratorIterator::SELF_FIRST); $paths = array(); // Paths storage foreach ($iterator as $k => $v) { // Loop thru each iterator if (!$iterator->hasChildren()) { // Check if iterator hasChildren is false $innermost = $iterator->getSubIterator($iterator->getDepth()); // Get innermost child which is the array for ($p = array(), $i = 0, $z = $iterator->getDepth(); $i <= $z; $i++) { // Loop and push each path to the innermost array $p[] = $iterator->getSubIterator($i)->key(); } array_pop($p); // Remove key $innermost = (array)$innermost; // Cast innermost to array $p[] = '(' . implode(', ', $innermost) . ')'; // push formatted innermost array to path $path = implode(' - ', $p); // implode the path $paths[] = $path; // store to list of paths array } } $paths = array_unique($paths); // remove exactly same paths foreach ($paths as $value) { // Loop and echo each path echo $value.'<br>'; }
Выход: – https://eval.in/915070
Я создал простую рекурсивную функцию. Для вашего примера. Сохраните предыдущие значения ключа в одной переменной и добавьте все данные в соответствии с предыдущим ключом и создайте новый массив (которые содержат все предыдущие ключи как индекс и последний элемент как значение). Попробуйте следующий код:
$obj = json_decode('{ "Group1": { "Blue": { "Round": [ "Harold", "Arthur", "Tom" ] }, "Green": { "Round": [ "Harold" ], "Circle": [ "Todd", "Mike" ] } }, "Group2": { "Blue": { "Round": [ "Peter" ] } } }', true); function traverse_array($array,$key="",$prev="",&$final_op=array()) { if(is_array($array)) { $prev .= $key." - "; foreach ($array as $key => $value) { traverse_array($value,$key,$prev,$final_op); } } else { $prev =trim($prev," - "); $final_op[$prev][]=$array; } return $final_op; } $data = traverse_array($obj); foreach ($data as $key => $value) { echo $key." (".implode(",", $value).")"; echo PHP_EOL; }
DEMO
Это работает для различной глубины массива, проверьте демо-версию .
while(count($array) != count($array, 1)) // stop when $array is one dimension { $temp = []; foreach($array as $k => $v) { if(is_array($v)) { if(count($v) != count($v, 1)) // check if reached the inner most array { foreach($v as $kk => $vv) { $temp[$k . ' - ' . $kk] = $vv; } } else $temp[$k] = '(' . implode($v, ', ') . ')'; }else $temp[$k] = $v; } $array = $temp; } foreach($array as $k => $v) echo $k . ' - ' . $v . "\n";
Заметка:
массив перемещения от внешнего к внутреннему
массив перемещения от внутреннего к внешнему
Попробуй это
Я создал рекурсивную программу, которую можно настроить
$obj = json_decode('{"Group1": { "Blue": { "Round": [ "Harold", "Arthur", "Tom" ] }, "Green": { "Round": [ "Harold" ], "Circle": [ "Todd", "Mike" ] } }, "Group2": { "Blue": { "Round": [ "Peter" ] } } }'); recursive($obj); function recursive($obj){ if(is_array($obj)){ foreach ($obj as $k => $v) { echo $v." "; } return; } foreach ($obj as $key => $value) { echo $key. " =>"; recursive($value); } echo "\n"; }
Ниже приведен образец
Group1 =>Blue =>Round =>Harold Arthur Tom Green =>Round =>Harold Circle =>Todd Mike Group2 =>Blue =>Round =>Peter
Я сводил мой метод к чему-то ОЧЕНЬ простым и легким для чтения. Для пояснения см. Встроенные комментарии. У меня есть две версии: 4-строчная функция эха и функция возврата массива.
* Обратите внимание, что этот метод очень СПЕЦИАЛЬНО построен для этого вопроса, потому что:
Метод №1 – эхо-строки внутри функции: ( Демо )
$array=json_decode('{ "Group1": { "Blue": { "Round": { "One": [ "Lawrence", "Anant", "B." ], "Two": [ "Erwin" ] } }, "Green": [ "Bryan", "Mick" ] }, "Group2": [ "Peter", "Kris" ] }', true); function recurse($array,$path=''){ foreach($array as $k=>$v){ if(!is_array(current($v))){ // check type of the first sub-element's value echo ($path?"$path > ":''),"$k > (".implode(', ',$v).")\n"; // don't recurse, just implode the indexed elements }else{ // recurse because at least 2 levels below recurse($v,($path?"$path > $k":$k)); // build path appropriately } } } recurse($array);
Вывод:
Group1 > Blue > Round > One > (Lawrence, Anant, B.) Group1 > Blue > Round > Two > (Erwin) Group1 > Green > (Bryan, Mick) Group2 > (Peter, Kris)
Метод # 2 – возвращает 4-элементный массив путей: ( Demo )
function recurse($array,$path='',&$result=[]){ foreach($array as $k=>$v){ if(!is_array(current($v))){ // check type of the first sub-element's value $result[]=($path?"$path > ":'')."$k > (".implode(', ',$v).')'; // don't recurse, just implode the indexed elements }else{ // recurse because at least 2 levels below recurse($v,($path?"$path > ":'').$k,$result); // build path appropriately } } return $result; } var_export(recurse($array));
Вывод:
array ( 0 => 'Group1 > Blue > Round > One > (Lawrence, Anant, B.)', 1 => 'Group1 > Blue > Round > Two > (Erwin)', 2 => 'Group1 > Green > (Bryan, Mick)', 3 => 'Group2 > (Peter, Kris)', )
И последнее обновление:
Лучший совет, который я могу дать, – это вырезать этот средний шаг и просто преобразовать вашу исходную строку json в новый желаемый результат (не требуется рекурсия / укладка):
Код: ( Демо )
$seperateArray = json_decode('[ { "tier1": "Group1", "tier2": "Blue", "tier3": "Round", "tier4": "One", "tier5": "Lawrence" }, { "tier1": "Group1", "tier2": "Blue", "tier3": "Round", "tier4": "One", "tier5": "Anant" }, { "tier1": "Group1", "tier2": "Blue", "tier3": "Round", "tier4": "One", "tier5": "B." }, { "tier1": "Group1", "tier2": "Blue", "tier3": "Round", "tier4": "Two", "tier5": "Erwin" }, { "tier1": "Group1", "tier2": "Green", "tier3": "Bryan" }, { "tier1": "Group1", "tier2": "Green", "tier3": "Mick" }, { "tier1": "Group2", "tier2": "Peter" }, { "tier1": "Group2", "tier2": "Kris" }]',true); foreach($seperateArray as $row){ $last_val=current(array_splice($row,-1)); // extract last element, store as string $results[implode(' > ',$row)][]=$last_val; } foreach($results as $k=>$v){ echo "$k > (",implode(', ',$v),")\n"; } // same output as earlier methods