Получение вложенных значений из ассоциативного массива - PullRequest
1 голос
/ 26 марта 2011

Это своего рода общий вопрос реализации.Если у меня есть произвольно глубокий массив, и я не знаю заранее, какими будут ключи, каков наилучший способ получить доступ к значениям в определенных путях ассоциативного массива?Например, учитывая массив:

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');, которое вернуло бы 'значение'

Пример кода Eval

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 ]

2 голосов
/ 26 марта 2011

Я не знаю о потенциальной скорости, но вам не нужно использовать 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;
0 голосов
/ 26 марта 2011

Вот и мы, мое решение:

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