5

I have array like this:

array(
    array(
        'id' => 1,
        'children' => array(
            array(
                'id' => 2,
                'parent_id' => 1
            ),
            array(
                'id' => 3,
                'parent_id' => 1,
                'children' => array(
                    array(
                        'id' => 4,
                        'parent_id' => 3
                    )
                )
            )
        )
    )
);

The array goes deeper if it's necessary. I need to get the children for any given id.

Thanks.

cnkt
  • 2,943
  • 5
  • 30
  • 43

4 Answers4

7
function getChildrenOf($ary, $id)
{
  foreach ($ary as $el)
  {
    if ($el['id'] == $id)
      return $el;
  }
  return FALSE; // use false to flag no result.
}

$children = getChildrenOf($myArray, 1); // $myArray is the array you provided.

Unless I'm missing something, iterate over the array looking for something that matches the id key and the id you're looking for (then return it as a result). You can also iteratively search (and give me a second to post code for that, which would examine the parentId key instead)...

--

Recursive Version, Includes Children Elements:

function getChildrenFor($ary, $id)
{
  $results = array();

  foreach ($ary as $el)
  {
    if ($el['parent_id'] == $id)
    {
      $results[] = $el;
    }
    if (count($el['children']) > 0 && ($children = getChildrenFor($el['children'], $id)) !== FALSE)
    {
      $results = array_merge($results, $children);
    }
  }

  return count($results) > 0 ? $results : FALSE;
}

Recursive Version, Excluding Children Elements

function getChildrenFor($ary, $id)
{
  $results = array();

  foreach ($ary as $el)
  {
    if ($el['parent_id'] == $id)
    {
      $copy = $el;
      unset($copy['children']); // remove child elements
      $results[] = $copy;
    }
    if (count($el['children']) > 0 && ($children = getChildrenFor($el['children'], $id)) !== FALSE)
    {
      $results = array_merge($results, $children);
    }
  }

  return count($results) > 0 ? $results : FALSE;
}
Brad Christie
  • 100,477
  • 16
  • 156
  • 200
  • It needs to be recursive as the array can be deeper – Rene Pot Dec 28 '11 at 13:49
  • @Topener: Question was changed mid-answer, so I'm fixing to accomodate. -- cnkt: Working on it, give me a minute or so. – Brad Christie Dec 28 '11 at 13:51
  • i changed question because people doesn't like var_dump outputs :) – cnkt Dec 28 '11 at 13:52
  • This function only checks the first layer. You need to check the childrens if the id dont match the one you looking for. Something like `[...] return $el; else return getChildrenOf($el, $id);` – Corubba Dec 28 '11 at 13:53
  • @cnkt: If you're looking to keep hierarchy, try this: http://www.ideone.com/5ovbW (otherwise I can fix to drop any children) -- EDIT: Here's an update without the `children` key: http://www.ideone.com/rusFS – Brad Christie Dec 28 '11 at 13:59
  • @BradChristie could you please help me out with this https://stackoverflow.com/questions/44804322/php-search-nested-array-of-array-and-return-only-matching-elements – Valay Jun 29 '17 at 13:42
2

You can use build in code for this

$iter = new RecursiveIteratorIterator(new RecursiveArrayIterator($array), RecursiveIteratorIterator::SELF_FIRST);
foreach ($iter as  $val) {
    if (isset($val['id']) && $val['id'] === 3) {
        print_r($val['children']);
        break;
    }
}
goat
  • 31,486
  • 7
  • 73
  • 96
1
function array_searchRecursive( $needle, $haystack, $strict=false, $path=array() )
{
    if( !is_array($haystack) ) {
        return false;
    }

    foreach( $haystack as $key => $val ) {
        if( is_array($val) && $subPath = array_searchRecursive($needle, $val,     $strict, $path) ) {
            $path = array_merge($path, array($key), $subPath);
            return $path;
        } elseif( (!$strict && $val == $needle) || ($strict && $val['id'] === $needle) ) {
            $path[] = $key;
            return $path;
        }
    }
    return false;
}

array_searchRecursive( 5, $arr );

-- reference : http://greengaloshes.cc/2007/04/recursive-multidimensional-array-search-in-php/

Wes Crow
  • 2,971
  • 20
  • 24
  • could you please help me out with this https://stackoverflow.com/questions/44804322/php-search-nested-array-of-array-and-return-only-matching-elements – Valay Jun 29 '17 at 13:57
1

A naive approach would be to do an exhaustive search on the tree by traversing the tree starting from the root until the node is found. In the worst case you have to iterate the whole tree only to note that the node you are looking for is the last node or not even existing.

A better approach would be to initially build an index that maps the IDs onto the nodes inside the tree. With this you would only need to traverse the whole tree once an then have direct access to the node via the index. Ideally, the indexing would be done during the tree structure is build from the flat data.

So if you have a flat array like in your other question, you can build both the tree and index from it with just one iteration of the flat array:

// array to build the final hierarchy
$tree = array(
    'children' => array()
);

// index array that references the inserted nodes
$index = array(0=>&$tree);

foreach ($arr as $key => $val) {
    // pick the parent node inside the tree by using the index
    $parent = &$index[$val['parent_id']];
    // append node to be inserted to the children array
    $node = $val;
    $parent['children'][$val['id']] = $node;
    // insert/update reference to recently inserted node inside the tree
    $index[$val['id']] = &$parent['children'][$val['id']];
}

This code is taken from my answer to a similar question. The final array you have posted is in $tree['children']. Each node in it can then be accessed with $index[12345].

Community
  • 1
  • 1
Gumbo
  • 643,351
  • 109
  • 780
  • 844