1

I have that array :

$a = array(
    "7" => array(
        "id" => 7,
        "parent" => 6
    ),
    "6" => array(
        "id" => 6,
        "parent" => 5
    ),
    "5" => array(
        "id" => 5,
        "parent" => 4
    ),
    "4" => array(
        "id" => 4,
        "parent" => 0
    ),
    "3" => array(
        "id" => 7,
        "parent" => 2
    ),
    "2" => array(
        "id" => 7,
        "parent" => 1
    ),
    "1" => array(
        "id" => 7,
        "parent" => 0
    )
);

the result that I want is that :

$a = array(
    "4" => array(
        "id" => 4,
        "parent" => 0,
        array(
            "5" => array(
                "id" => 5,
                "parent" => 4,
                array(
                    "6" => array(
                        "id" => 6,
                        "parent" => 5,
                        array(
                            "7" => array(
                                "id" => 7,
                                "parent" => 6
                            )
                        )
                    )
                )
            )
        )
    ),
    "2" => array(
        "id" => 7,
        "parent" => 1,
        array(
            "3" => array(
                "id" => 7,
                "parent" => 2
            )
        )
    ),
    "1" => array(
        "id" => 7,
        "parent" => 0
    )
);

the code that I use is this :

foreach($a as $v)
{
    if(isset($a[$v['PARENT']]))
    {
        $a[$v['PARENT']][$v['ID']] = $v;
        unset($a[$v['ID']]);
    }
}

and the problem that I have is that I get that result :

$a = array(
    "4" => array(
        "id" => 4,
        "parent" => 0,
        array(
            "5" => array(
                "id" => 5,
                "parent" => 4
            )
        )
    ),
    "2" => array(
        "id" => 7,
        "parent" => 1,
        array(
            "3" => array(
                "id" => 7,
                "parent" => 2
            )
        )
    ),
    "1" => array(
        "id" => 7,
        "parent" => 0
    )
);

instead of the need it result.

hakre
  • 193,403
  • 52
  • 435
  • 836
KodeFor.Me
  • 13,069
  • 27
  • 98
  • 166
  • I already gave you [solution](http://stackoverflow.com/questions/7671905/nested-array-to-html-list/7672073#7672073) for your problem in your previous question. Didn't it work? – binaryLV Oct 06 '11 at 10:56
  • I have change the form of the data that are comming from my database, and now it is not working. Now the problem is in other position. When I try to pass into the same array, a two dimonsional array into another array element the second dimension is disappearing. What's wrong with that ? :( – KodeFor.Me Oct 06 '11 at 11:00
  • The mistake you make is that you're removing values which you still need. That done, you unset every child of a child, [compare with my answer](http://stackoverflow.com/questions/7673044/nested-array-third-level-is-disappearing/7673415#7673415), which unsets, too, but references earlier so that the *actual* value does not get removed but preserved. – hakre Oct 06 '11 at 11:33

2 Answers2

4

To solve your problem you need to properly understand how variable referencing/aliasing in PHP works.

Look at the following example code, which does not look much different to yours but makes use of references in order to access any parent even it has already "moved":

# transform $flat into a tree:
foreach($flat as $id => &$value)
{
    # check if there is a parent
    if ($parentId = $value['parent'])
    {
        $flat[$parentId][0][$id] =& $value; # add child to parent
        unset($flat[$id]); # remove reference from topmost level
    }
}
unset($value); # remove iterator reference
print_r($flat); # your tree

$flat now contains all values from $flat - but reordered. Demo.

hakre
  • 193,403
  • 52
  • 435
  • 836
1

Are you sure that output array is correct? Surely the key 2 should be a child of 1 (since 2 has 'parent'=>1)? If this is not the case, I don't understand what are actually trying to do and how the keys all relate to each other.

If 2 should be a child of 1, this works:

$keep = array();
foreach ($a as $k => &$v) {
  // Loop the array first time and create references to
  // structure the array how you want it
  if ($v['parent']) {
    $a[$v['parent']][0] = array($k => &$v);
  } else $keep[] = $k;
}

foreach ($a as $k => $v) {
  // Loop it again to get rid of non-root nodes from the root
  if (!in_array($k,$keep)) {
    unset($a[$k]);
  }
}

print_r($a);
DaveRandom
  • 87,921
  • 11
  • 154
  • 174
  • You can put the code from the second foreach into the first one (before you changed the code with `$keep`). – hakre Oct 06 '11 at 11:36
  • @Hakre I did think about that, but I don't think you can - if you unset them as you go, and a later element has a parent of the one you have unset, it won't work. I think. I played around with it for a while and couldn't come up with a single loop that actually worked as expected. Would be happy to be proved wrong though... – DaveRandom Oct 06 '11 at 11:36
  • Check [my answer](http://stackoverflow.com/questions/7673044/nested-array-third-level-is-disappearing/7673415#7673415), it has a single loop. And a demo to play with. You can even move the `unset($flat[$id])` *above* the previous line which adds the child to the parent. – hakre Oct 06 '11 at 11:41