Nate
Nate

Reputation: 577

path to array value deep multidimensional array

I have an array where I need the path (keys) to a given value. I've written a function for it but I can't get it working, the array can have an infinite depth to be controlled in another function, I haven't decided on a limit yet but the depth is variable, it actually works up to a point but the depth may be 30-40-50 deep so I need it to work that way, this function is really just for value identification, the numbers are templates, the tags are tags in the templates, each tag has a single template associated with it, all template names are unique and tags names aren't because they are only associated with a single template, id values are separated by a dash (illegal in template and tag ids), where template ids are only numeric and tag ids are wrapped with squigglies and a dollar sign like so {$TAG}, don't have to worry about duplicate values because infinite loops are forbidden (template can't link to itself or a template that links to itself) plus ids are given only to templates where template names are unique. The id of the template named 4 in the given array would be 0-{$CONTENT}-2-{$PARAGRAPH}-4, where I lose it is my function won't go beyond this depth, thanks for the help

array (size=1)
  0 => 
    array (size=4)
      '{$TITLE}' => null
      '{$NAME}' => null
      '{$FRIENDS}' => 
          array (size=1)
            1 => 
              array (size=2)
                '{$friend}' => null
                '{$friends[$i]}' => null
      '{$CONTENT}' => 
        array (size=1)
          2 => 
             '{$HEADING}' => 
               array (size=1)
                 3 => 
                   array (size=0)
                     empty
             '{$PARAGRAPH}' => 
               array (size=1)
                 4 => 
                   array (size=1)
                     '{$AnotherParagraph}' => null

here is my function, I've added the depth variable just for testing purposes, $this->family is the array given above, calling the function: $id = $this->get_id(4);

public function get_id($member, $family=null, $id=null, $depth=0) {
    if (empty($this->family)) {
        return false;
    }
    if (is_null($family)) {
        $family = $this->family;
    }

    foreach ($family as $parent => $tag_child) {
        if ($member === $parent) {
            return $member;
        }

        foreach ($tag_child as $tag => $child) {
            if (is_null($child) || empty($child)) {
                continue;
            }

            $childkey = key($child);

            if ($member === $childkey) {
                $id .= '-'.$parent.'-'.$tag.'-'.$member;
                $id = ltrim($id, '-');
                return $id;
            }

            $family = $child;

            if (!is_null($id) && !empty($id)) {
                $id_array = explode('-', $id);
                foreach ($id_array as $id_value) {
                    if ($id_value !== $childkey) {
                        $new_id_array[] = $id_value;
                    }else{
                        break;
                    }
                }
                $id = implode('-', $new_id_array);
            }

            if ($parent === 0) {
                $id = $parent.'-'.$tag.'-'.$childkey;
            }else{
                $id .= '-'.$tag.'-'.$childkey;
            }

            $id = ltrim($id, '-');

            $depth++;

            $id = $this->get_id($member, $family, $id, $depth);

        }

    }
}

Upvotes: 0

Views: 426

Answers (1)

JRL
JRL

Reputation: 850

Use a recursive function. Here's one I wrote for this EXACT purpose.

public function recurseArray($array, $builtKey = "") {
    $values = array();
    foreach ($array as $key => $value) {
        if (is_array($value)) {
            if (!empty($builtKey)) {
                $values = array_merge($values, recurseArray($value, $builtKey.".".$key));
            } else {
                $values = array_merge($values, recurseArray($value, $key));
            }
        } else {
            if (!empty($builtKey)) {
                $values[$builtKey.".".$key] = $value;
            } else {
                $values[$key] = $value;
            }
        }
    }
    return $values;
}

This results in a flat array that transforms this:

array(
    "key" => array(
        "of" => array(
            "many" => array(
                "depths" => "value"
            )
        )
    ),
    "key2" => "value"
);

Into this:

array(
    "key.of.many.depths" => "value",
    "key2" => "value"
);

Upvotes: 1

Related Questions