递归循环数组的每个路径

时间:2017-12-08 04:13:10

标签: php arrays recursion multidimensional-array

我有以下(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?
}

6 个答案:

答案 0 :(得分:6)

仅对给定样本进行测试。但是如果阵列级别增加,这应该可行。我主要使用null类函数

RecursiveIteratorIterator

输出: - https://eval.in/915070

答案 1 :(得分:2)

这适用于阵列的不同深度,请检查live 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";

注意:

traverse array from outer to inner
traverse array from inner to outer

答案 2 :(得分:2)

我创建了简单的递归函数。对于你的例子。将以前的键值存储在一个变量中,并根据前一个键添加所有数据并创建新数组(其中包含所有以前的键作为索引,最后一个元素作为值)。请尝试以下代码:

$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

答案 3 :(得分:0)

试试这个

我创建了可以调整的样本递归程序

$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 :(得分:0)

我把我的方法简化为非常简单易读的东西。请参阅内联注释以获取解释。我有两个版本:一个4行回显函数和一个数组返回函数。

*请注意,此方法特别针对此问题而构建,因为:

  • 输入数组总是至少有两个级别的深度和

方法#1 - 从函数内部回显字符串:Demo

$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)',
)

最后一次更新:

我能给出的最好的建议是删除这个中间步骤并将your raw/initial json string转换为新的所需输出(不需要递归/堆叠):

代码:(Demo

$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

答案 5 :(得分:0)

这是我对发电机功能的看法:

function paths(array $a)
{
    // if first item is an array, recurse
    if (is_array(reset($a))) {
        foreach ($a as $k => $v) {
            foreach (paths($v) as $path) {
                // yield "key - subpath"
                yield sprintf('%s - %s', $k, $path);
            }
        }
    } else {
        // yield leaf
        yield sprintf('(%s)', implode(', ', $a));
    }
}

foreach (paths($obj) as $path) {
    printf("%s\n", $path);
}

试试online