Can someone help me with some code or instructions on how to walk recursively an array and when reaching the last element print the full path to it? A simple echo will work
This example is to give you idea, not to solve the actual task.
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');
If no match is found, null is returned.
<?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;
?>
Check code here
I found this solution, which also keeps into account if elements of the structure are arrays:
$file_contents=file_get_contents("data.json");
$json_dump=json_decode($file_contents);
printPath($json_dump, '', "" ,"");
function printPath($the_array, $path, $prevType) {
// Parse all elements of a structure
// and print full PHP path to each one.
foreach($the_array as $key => $value) {
if(is_array($value)) {
// Array element cannot be directly printed: process its items as objects:
printPath($value, $path . $key , "array");
} else {
if (!is_object($value)) { // If the element is not an object, it can be printed (it's a leaf)
if(is_string($value)) {
$finalValue = '"' . $value . '"';
} else {
$finalValue = $value;
}
if($prevType == "array") {
// If array element, add index in square brackets
echo($path . "[" . $key . "] = " . $finalValue . "<br>");
} else {
echo($path . $key . " = " . $finalValue . "<br>");
}
} else { // else store partial path and iterate:
if($prevType == "array") {
// Path of array element must contain element index:
printPath($value, $path . "[" . $key . "]->" , "dummy");
} else {
printPath($value, $path . $key . "->", "dummy");
}
}
}
}
}
Example output:
status->connections->DSS-25->band = "X"
status->connections->DSS-25->endAt = "2019-11-20T20:40:00.000Z"
status->connections->DSS-25->startAt = "2019-11-20T12:40:00.000Z"
geometry[0]->obs[0]->name = "UDSC64"
geometry[0]->obs[0]->hayabusa2->azm = 90.34
geometry[0]->obs[0]->hayabusa2->alt = -20.51
In case anybody is interested, here it is the port to Javascript:
function iterate(obj, stack, prevType) {
for (var property in obj) {
if ( Array.isArray(obj[property]) ) {
//console.log(property , "(L=" + obj[property].length + ") is an array with parent ", prevType, stack);
iterate(obj[property], stack + property , "array");
} else {
if ((typeof obj[property] != "string") && (typeof obj[property] != "number")) {
if(prevType == "array") {
//console.log(stack + "[" + property + "] is an object, item of " , prevType, stack);
iterate(obj[property], stack + "[" +property + "]." , "object");
} else {
//console.log(stack + property , "is " , typeof obj[property] , " with parent ", prevType, stack );
iterate(obj[property], stack + property + ".", "object");
}
} else {
if(prevType == "array") {
console.log(stack + "[" + property + "] = "+ obj[property]);
} else {
console.log(stack + property , " = " , obj[property] );
}
}
}
}
}
iterate(object, '', "File")
I just wrote a function that makes recursive looping a bit easier: Similar to array_walk_recursive but with some extra functionality
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;
}
Called like so:
$result = Namespace\ClassName::walk($array, ['Namespace\ClassName', 'walkable'], ['key'=>'value'], true);
Setting recursive to false will only evaluate the first level.
Setting recursive to true will cause it to traverse the entire array.
Setting recursive to an integer will cause it to only traverse to that depth.
Walkable functions can be referenced or passed to callback as anonymous function.
(expects: value, key, custom, info) The returned value replace the current value.
Custom data can be passed and some additional info is provided for you.
You can expand on the walk function if you need additional info.
$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;
}
You can add a third parameter which holds the actual path as String. At the end you can output it then.