3

Wrecking my brains for a while now and need your help

I have an array as below:

$originalArray = array(
    array('id' => 1, 'sub-id' => 0),
    array('id' => 2, 'sub-id' => 0),
    array('id' => 3, 'sub-id' => 1),
    array('id' => 4, 'sub-id' => 3),
    array('id' => 5, 'sub-id' => 4),
    array('id' => 6, 'sub-id' => 0),
    array('id' => 7, 'sub-id' => 0),
    array('id' => 8, 'sub-id' => 6),
    array('id' => 9, 'sub-id' => 8),
    array('id' => 10, 'sub-id' => 8)
);

and the logic here is

if sub-id of any element is equal to the id of another element, then the array goes into the sub key of the parent element. i.e. sub-id 1 should go in 'sub' element of id 1 and sub-id 3 should go in 'sub' element of id 3

The required output of the above array is:

$requiredArray = array(
    array('id' => 1,'sub-id' => 0,
        'sub' => array(
            array('id' => 3,'sub-id' => 1,
                'sub' => array(
                    array('id' => 4,'sub-id' => 3,
                        'sub' => array(
                            array('id' => 5,'sub-id' => 4)
                        )
                    )
                )
            )
        )
    ),
    array('id' => 2,'sub-id' => 0),
    array('id' => 6,'sub-id' => 0,
        'sub' => array(
            array('id' => 8,'sub-id' => 6,
                'sub' => array(
                    array('id' => 9,'sub-id' => 8),
                    array('id' => 10,'sub-id' => 8)
                )
            )
        )
    ),
    array('id' => 7,'sub-id' => 0)
);

What have I tried so far

// $original array is the array shown above
function compare_subid($a, $b)
{
    if ($a['sub-id'] == $b['sub-id']) return 0;
    return ($a['sub-id'] < $b['sub-id']) ? -1 : 1;
}

usort($originalArray, 'compare_subid');

$newArray = array();
$newArray = create_multidimensional($originalArray, $newArray);

function create_multidimensional($originalArray, $newArray = null)
{
    if ($newArray == null) $newArray = array();
    array_walk($originalArray, function ($value, $key) use (&$newArray) {
        //e($value);
        if ($value['sub-id'] == 0) {
            $newArray[] = $value;
        } else {
            foreach ($newArray as &$v) {
                if ($v['id'] == $value['sub-id']) {
                    $v['sub'] = $value;
                } else {
                    // not sure what to put here
                }
            }
        }
    });
    return $newArray;
}

With this i am able to achieve a part of the $requiredArray which is as follows:

Array
(
    [0] => Array
        (
            [id] => 6
            [sub-id] => 0
            [sub] => Array
                (
                    [id] => 8
                    [sub-id] => 6
                )

        )

    [1] => Array
        (
            [id] => 7
            [sub-id] => 0
        )

    [2] => Array
        (
            [id] => 2
            [sub-id] => 0
        )

    [3] => Array
        (
            [id] => 1
            [sub-id] => 0
            [sub] => Array
                (
                    [id] => 3
                    [sub-id] => 1
                )

        )
)

Not sure if this is the correct method to use or there is any better way to do so.

If what I am doing is correct, I am not able to figure out what to input in the else statement of create_multidimensional function that I have created.

2 Answers 2

2

There is an easy way using references and only remove the ones with a sub-id at the very end:

// We need keys to be able to quickly map our assignments
foreach ($originalArray as $val) {
    $array[$val["id"]] = $val;
}

// we first assign the arrays in a non-destructive way, so that we can easily find the
// appropriate key in the array
foreach ($array as $key => $val) {
    if ($val["sub-id"] !== 0) {
        $array[$val["sub-id"]]["sub"][] = &$array[$key];
    }
}

// remove the ones from the first dimension which are somewhere deeper
foreach ($array as $key => $val) {
    if ($val["sub-id"] !== 0) {
        unset($array[$key]);
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

@Guns should work now, I initially didn't notice that $originalArray["id"] != $key...
2

This is why objects in PHP are cool.

// Format all data into objects keyed by id
$input = array();
foreach ($originalArray as $el) {
  $input[ $el['id'] ] = (object)($el + array('sub' => array()));
}

$result = array();
foreach ($input as $el) {
  $sid = $el->{'sub-id'};

  // Parent object: into result root
  if ( !$sid ) {
    $result[] = $el;
  }
  // Child object: into other object
  else {
    $input[$sid]->sub[] = $el;
  }
}

print_r($result);

The obvious downside is that objects use ->prop syntax, which doesn't work well with -, so you have to ugly it: $el->{'sub-id'}.

And of course the result is a bunch of objects. May not be what you want.

Result (http://3v4l.org/8VMJr):

Array
(
    [0] => stdClass Object
        (
            [id] => 1
            [sub-id] => 0
            [sub] => Array
                  (
                    [0] => stdClass Object
                        (
                            [id] => 3
                            [sub-id] => 1
                            [sub] => Array
                                (
                                    [0] => stdClass Object
                                        (
                                            [id] => 4
                                            [sub-id] => 3
                                            [sub] => Array
                                                (
                                                    [0] => stdClass Object
                                                        (
                                                            [id] => 5
                                                            [sub-id] => 4
                                                            [sub] => Array
                                                                (
                                                                )
                                                        )
                                                )
                                        )
                                )
                        )
                )
        )
    [1] => stdClass Object
        (
            [id] => 2
            [sub-id] => 0
            [sub] => Array
                (
                )
        )
    [2] => stdClass Object
        (
            [id] => 6
            [sub-id] => 0
            [sub] => Array
                (
                    [0] => stdClass Object
                        (
                            [id] => 8
                            [sub-id] => 6
                            [sub] => Array
                                (
                                    [0] => stdClass Object
                                        (
                                            [id] => 9
                                            [sub-id] => 8
                                            [sub] => Array
                                                (
                                                )
                                        )
                                    [1] => stdClass Object
                                        (
                                            [id] => 10
                                            [sub-id] => 8
                                            [sub] => Array
                                                (
                                                )
                                        )
                                )
                        )
                )
        )
    [3] => stdClass Object
        (
            [id] => 7
            [sub-id] => 0
            [sub] => Array
                (
                )
        )
)

3 Comments

+1 Nice. But you just could say that's why references are cool in PHP :-P
No, references are tricky bitches. Unexpected stuff happens. In an object only its properties are by-reference, which is cooler, I think. Maybe I'm just not as good! =)
References are just as long tricky as long you use them globally and not only locally to perform quick tasks. If you use them globally, it might cause to break random things. But when you control precisely what you do with them, no problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.