从关联数组获取嵌套值

时间:2011-03-25 21:39:48

标签: php data-structures eval

这是一般性实施问题。如果我有一个任意深度的数组,并且我事先不知道键是什么,访问关联数组的特定路径上的值的最佳方法是什么?例如,给定数组:

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

$array['great-grandparent']['grandparent']['parent']['child']访问价值的最佳方式是什么,请记住我事先不知道密钥。我使用eval将上面的语法构造为带有变量名的字符串,然后eval'd字符串以获取数据。但是eval很慢,我希望得到更快的东西。类似$class->getConfigValue('great-grandparent/grandparent/'.$parent.'/child');的东西会返回'value'

评估代码示例

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;
    }

2 个答案:

答案 0 :(得分:2)

我不知道潜在的速度,但您不需要使用eval进行类似的搜索:

  $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;

答案 1 :(得分:0)

我们走了,我的解决方案:

$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;
}