Recursively cycle every path of an array

后端 未结 6 1792
[愿得一人]
[愿得一人] 2021-01-01 01:02

I have the following(json) object:

$obj = json_decode(\'{
    \"Group1\": {
        \"Blue\": {
            \"Round\": [
                \"Harold\",
                 


        
6条回答
  •  渐次进展
    2021-01-01 01:13

    I've boiled down my method to something VERY simple and easy to read. See inline comments for explanations. I have two versions: a 4-line echoing function and an array returning function.

    *Note this method is very SPECIFICALLY built for this question because:

    • The input array will ALWAYS have a depth of at least two levels AND

    Method #1 - echo strings from inside the function: (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);
    

    Output:

    Group1 > Blue > Round > One > (Lawrence, Anant, B.)
    Group1 > Blue > Round > Two > (Erwin)
    Group1 > Green > (Bryan, Mick)
    Group2 > (Peter, Kris)
    

    Method #2 - return a 4-element array of paths: (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));
    

    Output:

    array (
      0 => 'Group1 > Blue > Round > One > (Lawrence, Anant, B.)',
      1 => 'Group1 > Blue > Round > Two > (Erwin)',
      2 => 'Group1 > Green > (Bryan, Mick)',
      3 => 'Group2 > (Peter, Kris)',
    )
    

    And one final update:

    The best advice I can give would be to cut out this middle step and just convert your raw/initial json string to your new desired output (no recursion/stacking required):

    Code: (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
    

提交回复
热议问题