简体   繁体   English

在PHP中将数组重组为树结构

[英]Regroup array to tree structure in PHP

I have an array like this one: 我有一个像这样的数组:

$array = array(
    array('id' => 'foo.bar'),
    array('id' => 'foo'),
    array('id' => 'foo.baz.bar'),
    array('id' => 'foo.bar.bar'),
);

I can split the id fields to get them as paths, and then I'd like to sort them into a tree... I tried this: 我可以split id字段split为路径,然后将它们排序为树...

$result = array();

foreach($array as $element) {
    $path = explode('.', $element['id']);

    $subtree = $result;
    while(!empty($path)) {
        $path_element = array_shift($path);

        if(empty($path_element)) {
            $subtree['data'] = $element;
        } else {
            if(!is_array($subtree[$path_element])) {
                $subtree[$path_element] = array();
            }
            $subtree = $subtree[$path_element];
        }
    }
}

But all I get is a load of warnings and an empty $res -Array. 但是我得到的只是大量警告和一个空的$res -Array。

PHP Notice:  Undefined index: foo in tree.php on line 24
PHP Stack trace:
PHP   1. {main}() tree.php:0
PHP Notice:  Undefined index: bar in tree.php on line 24
PHP Stack trace:
PHP   1. {main}() tree.php:0
PHP Notice:  Undefined index: foo in tree.php on line 24
PHP Stack trace:
PHP   1. {main}() tree.php:0
PHP Notice:  Undefined index: foo in tree.php on line 24
PHP Stack trace:
PHP   1. {main}() tree.php:0
PHP Notice:  Undefined index: baz in tree.php on line 24
PHP Stack trace:
PHP   1. {main}() tree.php:0
PHP Notice:  Undefined index: bar in tree.php on line 24
PHP Stack trace:
PHP   1. {main}() tree.php:0
PHP Notice:  Undefined index: foo in tree.php on line 24
PHP Stack trace:
PHP   1. {main}() tree.php:0
PHP Notice:  Undefined index: bar in tree.php on line 24
PHP Stack trace:
PHP   1. {main}() tree.php:0
PHP Notice:  Undefined index: bar in tree.php on line 24
PHP Stack trace:
PHP   1. {main}() tree.php:0

(Line 24 is $s = $s[$pe]; ) (第24行是$s = $s[$pe];

Any hint? 有什么提示吗?

EDIT : My desired output would be like this 编辑 :我想要的输出将是这样

$res = array(
  'foo' => array(
    'data' => ...
    'bar' => array(
      'data' => ...
      'bar' => array(
        'data' => ...
      ),
    ),
    'baz' => array(
      'bar' => array(
        'data' => ...
      ),
    ),
  ),
);

The data elements are the original elements from the array. data元素是数组中的原始元素。

The code below generates the following result: 下面的代码生成以下结果:

Array
(
    [foo] => Array
    (
        [data] => ...
        [baz] => Array
            (
                [bar] => Array
                    (
                        [data] => ...
                    )

        )

        [bar] => Array
        (
            [bar] => Array
            (
                [data] => ...
            )
        )
    )
)

I renamed some of you're variables... 我重命名了一些变量...

$array = array(
    array('id' => 'foo.bar'),
    array('id' => 'foo'),
    array('id' => 'foo.baz.bar'),
    array('id' => 'foo.bar.bar'),
);


$res = array();

foreach($array as $e) {

    $parts = explode('.', $e['id']);

    $temp = &$res;

    foreach($parts as $key => $el) {
        if (!isset($temp[$el])) $temp[$el] = array();

        if ($key == count($parts)-1) $temp[$el] = array('data' =>  '...');
        $temp = &$temp[$el];
    }
}

print_r($res);

Make $s referencing $res, using the & . 使用&使$ s引用$ res。 This will pass the data by reference instead of by value. 这将通过引用而不是通过值传递数据。

$a = array(
    array('id' => 'foo.bar'),
    array('id' => 'foo'),
    array('id' => 'foo.baz.bar'),
    array('id' => 'foo.bar.bar'),
);

$res = array();

foreach($a as $e) {
    $p = explode('.', $e['id']);

    $s = &$res;
    while(!empty($p)) {
        $pe = array_shift($p);
        if(empty($p)) {
            $s['data'] = $e;
        } else {

            if(!isset($s[$pe])) {
                $s[$pe] = array();
            }
            $s = &$s[$pe];
        }
    }
}

echo '<pre>';
print_r($res);
echo '</pre>';

results in 结果是

Array
(
    [foo] => Array
        (
            [data] => Array
                (
                    [id] => foo.bar
                )

            [baz] => Array
                (
                    [data] => Array
                        (
                            [id] => foo.baz.bar
                        )

                )

            [bar] => Array
                (
                    [data] => Array
                        (
                            [id] => foo.bar.bar
                        )

                )

        )

    [data] => Array
        (
            [id] => foo
        )

)

Recursion is your answer. 递归是您的答案。

and you would need something along the lines of: 并且您需要以下方面的东西:

<?php

$a = array(
    array('id' => 'foo.bar'),
    array('id' => 'foo'),
    array('id' => 'foo.baz.bar'),
    array('id' => 'foo.bar.bar'),
);

function createTree($path) {
    if ( count($path) === 1 ) {
        return array($path[0]=>array('data'=>'some random data here'));
    } else {
        $currentRoot = array_shift($path);
        return array($currentRoot => createTree($path));
    }
}

$result = array();

foreach ( $a as $item ) {
    $result = array_merge_recursive(
        $result,
        createTree(
            explode('.',$item['id'])
        )
    );
}

// $result now is what you wanted

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM