1

This is sort of a general implementation question. If I have an arbitrarily deep array, and I do not know before hand what the keys will be, what is the best way to access the values at specific paths of the associative array? For example, given the array:

array(
    'great-grandparent' = array(
        'grandparent' = array(
             'parent' = array(
                  'child' = 'value';
              ),
              'parent2' = 'value';
         ),
         'grandparent2' = 'value';
    )
);

Whats the best way to access the value at $array['great-grandparent']['grandparent']['parent']['child'] keeping in mind that I don't know the keys beforehand. I have used eval to construct the above syntax as a string with variable names and then eval'd the string to get the data. But eval is slow and I was hoping for something faster. Something like $class->getConfigValue('great-grandparent/grandparent/'.$parent.'/child'); that would return 'value'

Example of Eval Code

public function getValue($path, $withAttributes=false) {
        $path = explode('/', $path);
        $rs = '$r = $this->_data[\'config\']';
        foreach ($path as $attr) {
            $rs .= '[\'' . $attr . '\']';
        }
        $rs .= ';';
        $r = null;
        @eval($rs);
        if($withAttributes === false) {
            $r = $this->_removeAttributes($r);
        }
        return $r;
    }
4
  • You're evaling? Can you show us an example of that? Commented Mar 25, 2011 at 21:43
  • added the eval code. It's basically taking a / delimited path and turning it into array access syntax then evaling. Commented Mar 25, 2011 at 21:50
  • Are you implementing a config system with this? Commented Mar 25, 2011 at 21:50
  • yes. ha i need more characters for a comment so here they are Commented Mar 25, 2011 at 21:52

2 Answers 2

2

I don't know about the potential speed but you don't need to use eval to do a search like that :

  $conf = array(
      'great-grandparent' => array(
          'grandparent' => array(
               'parent' => array(
                    'child' => 'value searched'
                ),
                'parent2' => 'value'
           ),
           'grandparent2' => 'value'
      )
  );

  $path = 'great-grandparent/grandparent/parent/child';
  $path = explode('/', $path);

  $result = $conf;

  while(count($path) > 0) {
      $part = array_shift($path);

      if (is_array($result) && array_key_exists($part, $result)) {
          $result = $result[$part];
      } else {
          $result = null;
          break;
      }
  }

  echo $result;
Sign up to request clarification or add additional context in comments.

2 Comments

+1 Been working myself on an algorithm :) Your solution does not work 100% correct I think, try a path like this great-grandparent/grandparent2/parent2 I get a v as output which should not be correct.
@Nick Weaver: Oh i didn't manage the error cases in my sample, added it now.
0

Here we go, my solution:

$tree = array(
    'great-grandparent' => array(
        'grandparent' => array(
             'parent' => array(
                  'child' => 'value1'
              ),
              'parent2' => 'value2'
         ),
         'grandparent2' => 'value3'
    )
);

$pathParts = explode('/','great-grandparent/grandparent/parent/child');
$pathParts = array_reverse($pathParts);

echo retrieveValueForPath($tree, $pathParts);

function retrieveValueForPath($node, $pathParts)  {
    foreach($node as $key => $value) {
        if(($key == $pathParts[count($pathParts)-1]) && (count($pathParts)==1)) {
            return $value;
        }       

        if($key == $pathParts[count($pathParts)-1]) {
            array_pop($pathParts);
        }

        if(is_array($value)) {
            $result = retrieveValueForPath($value, $pathParts);
        }
    }

    return $result;
}

2 Comments

I had an xml implementation as well but xml is so slow to parse, i thought someone on here might have a simple solution I overlooked. The problem with xml is the complexity involved when merging nodes and node inheritance
The parse_ini returns an array which I have already created so no need to get an array from an ini file

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.