Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I'm using a multidimensional PHP array to keep track of objects, like this:

Array(
    ["name1"] => Array(
        ["data"] => Array(
           ["children"] => Array(
               ["name2"] => Array(
                   ["data"] => Array(
                       ["otherData"] => 2
                   )
               ),
               ["name3"] => Array(
                   ["data"] => Array()
               )
           )
        )
    ),
    ["name4"] => Array(
        ["data"] => Array(
            ["someRandomValue"] => "hi"
        )
    )
)

This could be any number of levels, and so I would

need a recursive function to add a new object into it.

I'd like to do something like this:

function addToArray($item, $array) {
    if ($item-getData('insertBefore')) {
        //...
    }
    if ($item-getData('insertAfter')) {
        //...
    }
    if ($item-getData('parent')) {
        //...
    }
    foreach($array as &$arraySlice) {
        //..magic here
    }
}

Basically the function would try to honor the 3 data options parent, insertBefore and insertAfter as best as it can. If conflicting info with before & after it would give an error and with missing parent (and before/after) info just append as last index, after "name4".

So that a new item called name5

with parent set to name1 and

insertBefore set to name3 is inserted like this:

Array(
    ["name1"] => Array(
        ["data"] => Array(
           ["children"] => Array(
               ["name2"] => Array(
                   ["data"] => Array(
                       ["otherData"] => 2
                   )
               ),
               ["name5"] => Array(
                   ["data"] => Array(
                       ["parent"] => "name1",
                       ["insertBefore"] => "name3"
                   )
               ),
               ["name3"] => Array(
                   ["data"] => Array()
               )
           )
        )
    ),
    ["name4"] => Array(
        ["data"] => Array(
            ["someRandomValue"] => "hi"
        )
    )
)

Any suggestions? I can't seem to get it right in my attempts. Another function to remove any "nameX" entry would be great too.


EDIT: here's my latest try before I got confused enought to give up

function addToArray($item, $array) {
    $parent = isset($item->getData('parent'))   ? $item->getData('parent')   : null;
    $before = isset($item->getData('insertBefore')) ? $item->getData('insertBefore') : null;
    $after  = isset($item->getData('insertAfter'))  ? $item->getData('insertAfter')  : null;

    $parentFound = null;
    $prevPart    = null;

    // use & in the loop to work with a reference
    foreach($layout as $key => &$part) {
        if ($key == $parent) {
            $parentFound = 1;
        }

        if ($parentFound || !$parent) {
            if ($after) {
                //..
            }
            if ($before) {
                //..
            }
            //eh, erhm..
        } else if ($part['data']['children']) {
            if (addToArray($item, $part)) {
                return true;
            }
        }
        $prevPart = $part;
    }
    return false;
}
share|improve this question
1  
What are your unsuccessful attempts ? –  Clément Malet Aug 14 at 11:52
    
Well for one thing I don't even know how to insert into the original array once I recursively have found the position it should be in. Keep count of where I am and use some sort of array_splice and array_merge thing? Or maybe it's better to build a separate copy of the original array as I walk through it and then replace (or merge with) the original once I've built the copy? I'm basically stuck in my thinking and right now I have no complete function to show since I've thrown away most attempts halfway through. –  Christoffer Bubach Aug 14 at 11:58
1  
"name" keys are unique over your structure at least ? –  Clément Malet Aug 14 at 12:05
    
Yes they are, and also I added my latest half-finished try to the post. –  Christoffer Bubach Aug 14 at 12:06
    
smells like XY problem. Maybe tell us what you are actually trying to do –  Pinoniq Aug 14 at 12:12

1 Answer 1

up vote 0 down vote accepted

Its quite hard to help you on such a problem without setting up a big base of code to test, so I'm giving you a strong and commented base to start with.

function my_recc_func ($parent, $before, $after, $array, $my_data) {

  // Lets search the name in the keys of my current node (root or children)
  foreach ($array as $key => $value) {
    if ($key == $parent) {
      // Found it, so I'll do something here, and return true anyway
      $pos = 0;
      // Now looking for after or before names, and finding the correct pos at which I want to add my_data
      foreach ($value[$data][$children] as $name => $arr) {
        ++$pos;
        if ($name == $after) {
          break;
        }
        if ($name == $before) {
          --$pos;
          break;
        }
      }
      // Using the array_slice trick to insert my_data where I want inside of the array
      // It is now my new children with data inserted
      $new_children = array_slice ($value[$data][$children], 0, $pos, true) + $my_data + array_slice, $pos, count($value[$data][$children]), true);
      // $value[$data][$children] becomes $new_children
      // Code it as you want, if you need references or not or with a temporary array
      return true;
    } else {
      // That name isn't the correct one, so I'll see in the children of that node
      if (my_recc_func($parent, $before, $after, $value[$data][$children])) {
        return true;
      }
      // If I didn't find it in the children nodes, I'll keep going with the following nodes of the current parent
    }
  }
  // Didn't find anything in the children or in the current node, bye
  return false;

}

You might need to apply some changes to get it to work (as you said using references, or checking for incoherence between before and after) but the main logic is here.

Hope it helps you to get something effective.

Edit : Ok, gave a look at your last attempt, and it seems like you already had something very similar. If you tell me what you problem was with that code, I'll help you to make it work

share|improve this answer
    
Looks good, even just the position count and the array slice parts might help me solve this. I will test later today and get back to you on my results. Thanks! –  Christoffer Bubach Aug 14 at 12:55
    
Hi, after a few hours of fiddling around with references and whatnot I managed to get it to work - thank you for your help! –  Christoffer Bubach 2 days ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.