PHP - Array - Recursively print each full branch (up to leaf/leaves) of the nested array (Tree) as an Xpath

本小妞迷上赌 提交于 2019-12-25 17:19:33

问题


Have this code:

$text = '{"token_name":"C_ROOT","token_group":"C_BLOCK","group":true,"body":[[{"token_name_org":"T_VARIABLE","token":320,"value":"sort","line":2,"token_group":"VARIABLES","token_name":"C_VARIABLE"},{"token_name_org":"C_ASSIGNMENT_EQUAL","line":2,"value":"=","token":"VALUE","token_group":"ASSIGNMENTS"},{"token_name_org":"T_VARIABLE","token":320,"value":"_GET","line":2,"token_group":"VARIABLES","token_name":"C_VARIABLE","args":[[{"token_name_org":"T_CONSTANT_ENCAPSED_STRING","token":323,"value":"sort","line":2,"token_group":"STRINGS","token_name":"C_STRING"}]]}],[{"token_name_org":"T_VARIABLE","token":320,"value":"mort","line":2,"token_group":"VARIABLES","token_name":"C_VARIABLE"},{"token_name_org":"C_ASSIGNMENT_EQUAL","line":2,"value":"=","token":"VALUE","token_group":"ASSIGNMENTS"},{"token_name_org":"T_VARIABLE","token":320,"value":"_GET","line":2,"token_group":"VARIABLES","token_name":"C_VARIABLE","args":[[{"token_name_org":"T_CONSTANT_ENCAPSED_STRING","token":323,"value":"mort","line":2,"token_group":"STRINGS","token_name":"C_STRING"}]]}],[{"token_name_org":"T_VARIABLE","token":320,"value":"bort","line":2,"token_group":"VARIABLES","token_name":"C_VARIABLE"},{"token_name_org":"C_ASSIGNMENT_EQUAL","line":2,"value":"=","token":"VALUE","token_group":"ASSIGNMENTS"},{"token_name_org":"T_VARIABLE","token":320,"value":"_GET","line":2,"token_group":"VARIABLES","token_name":"C_VARIABLE","args":[[{"token_name_org":"T_CONSTANT_ENCAPSED_STRING","token":323,"value":"bort","line":2,"token_group":"STRINGS","token_name":"C_STRING"}]]}]]}';

$array = json_decode($text, TRUE);


// Collect the values here.
// Start with an empty string to force a leading '/' in the output
$path = array('');
// Walk the array, put the desired values in $path
array_walk_recursive(
    $array,
    function($value, $key) use (&$path) {      // use reference to modify $path inside the function
        if ($key == 'value' ) {
            $path[] = $value;
        }
    }
);

// Join the collected values and output the result
echo(implode('/', $path));

It goes through the Array (Tree) and prints Xpath for each branch, up to the leaves:

Prettified array as JSON:

{
  "token_name": "C_ROOT",
  "token_group": "C_BLOCK",
  "group": true,
  "body": [
    [
      {
        "token_name_org": "T_VARIABLE",
        "token": 320,
        "value": "sort",
        "line": 2,
        "token_group": "VARIABLES",
        "token_name": "C_VARIABLE"
      },
      {
        "token_name_org": "C_ASSIGNMENT_EQUAL",
        "line": 2,
        "value": "=",
        "token": "VALUE",
        "token_group": "ASSIGNMENTS"
      },
      {
        "token_name_org": "T_VARIABLE",
        "token": 320,
        "value": "_GET",
        "line": 2,
        "token_group": "VARIABLES",
        "token_name": "C_VARIABLE",
        "args": [
          [
            {
              "token_name_org": "T_CONSTANT_ENCAPSED_STRING",
              "token": 323,
              "value": "sort",
              "line": 2,
              "token_group": "STRINGS",
              "token_name": "C_STRING"
            }
          ]
        ]
      }
    ],
    [
      {
        "token_name_org": "T_VARIABLE",
        "token": 320,
        "value": "mort",
        "line": 2,
        "token_group": "VARIABLES",
        "token_name": "C_VARIABLE"
      },
      {
        "token_name_org": "C_ASSIGNMENT_EQUAL",
        "line": 2,
        "value": "=",
        "token": "VALUE",
        "token_group": "ASSIGNMENTS"
      },
      {
        "token_name_org": "T_VARIABLE",
        "token": 320,
        "value": "_GET",
        "line": 2,
        "token_group": "VARIABLES",
        "token_name": "C_VARIABLE",
        "args": [
          [
            {
              "token_name_org": "T_CONSTANT_ENCAPSED_STRING",
              "token": 323,
              "value": "mort",
              "line": 2,
              "token_group": "STRINGS",
              "token_name": "C_STRING"
            }
          ]
        ]
      }
    ],
    [
      {
        "token_name_org": "T_VARIABLE",
        "token": 320,
        "value": "bort",
        "line": 2,
        "token_group": "VARIABLES",
        "token_name": "C_VARIABLE"
      },
      {
        "token_name_org": "C_ASSIGNMENT_EQUAL",
        "line": 2,
        "value": "=",
        "token": "VALUE",
        "token_group": "ASSIGNMENTS"
      },
      {
        "token_name_org": "T_VARIABLE",
        "token": 320,
        "value": "_GET",
        "line": 2,
        "token_group": "VARIABLES",
        "token_name": "C_VARIABLE",
        "args": [
          [
            {
              "token_name_org": "T_CONSTANT_ENCAPSED_STRING",
              "token": 323,
              "value": "bort",
              "line": 2,
              "token_group": "STRINGS",
              "token_name": "C_STRING"
            }
          ]
        ]
      }
    ]
  ]
}

Output:

/sort/=/_GET/sort/mort/=/_GET/mort/bort/=/_GET/bort

Anybody have an idea how can I count the number of nested arrays, know when to stop, where the branch ends? Also how can I specify to search only for "sort", branches "mort" and "bort" should not appear.

The output should be, based on search "sort":

/sort/=/_GET/sort

So the pseudocode should be I think something like this:

  1. Find in "body" array with key "value" equal to what is search for (i.e "sort")
  2. Get all the siblings and children, children's children etc key "value" value until the branch ends.
  3. Print the branch
  4. Goto 1 for next body item

Thanks,


回答1:


First you have to identify that item of body that contains value == 'sort' then apply the existing code (extract it in a function first):

$search = 'sort';

// Identify the items having 'value' associated with $search
$allItems = array_filter(
    $array['body'],
    function (array $item) use ($search) {
        // $item contains many tokens, keep $item if the first token has value == 'sort'
        // just to be sure you can also check here if $item[0]['token'] is 320 or the value of 'token_org_name'
        return $item[0]['value'] == $search;
    }
);

// Pass all the found items to the function that produces the path
foreach ($allItems as $item) {
   echo(getPath($item)."\n");
}


function getPath(array $array) {
    // Collect the values here.
    // Start with an empty string to force a leading '/' in the output
    $path = array('');
    // Walk the array, put the desired values in $path
    array_walk_recursive(
        $array,
        function($value, $key) use (&$path) {
            if ($key == 'value' ) {
                $path[] = $value;
            }
        }
    );

    // Join the collected values and return the result
    return implode('/', $path);
}


来源:https://stackoverflow.com/questions/44699113/php-array-recursively-print-each-full-branch-up-to-leaf-leaves-of-the-nest

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!