У меня есть массив папок / путей:
$arr = Array ( 0 => Array ( 'name' => 'aaa' ), 1 => Array ( 'name' => 'aaa\bbb' ), 2 => Array ( 'name' => 'aaa\bbb\ccc' ), 3 => Array ( 'name' => 'ddd' ) );
Я хотел бы преобразовать его в многомерный (древовидный) массив (сохраняя структуру: index / key & value / name):
aaa bbb ccc ddd
Есть предложения?
Пытаться:
$arr = array( array('name' => 'aaa'), array('name' => 'aaa\bbb'), array('name' => 'aaa\bbb\ccc'), array('name' => 'ddd'), array('name' => 'ddd\zzz'), array('name' => 'zzz'), array('name' => 'ddd\zzz\fff'), ); $new = array(); $helper = array(); foreach ($arr as $i => $entry) { $parent =& $new; /** * One could use: * explode(DIRECTORY_SEPARATOR, $entry['name']) * * instead of '\\' if you're dealing with file-structures */ foreach ($path = explode('\\', $entry['name']) as $ii => $element) { $subPath = implode('.', array_slice($path, 0, $ii + 1)); if (isset($helper[$subPath])) { $parent =& $helper[$subPath]; continue; } $parent[$i] = array('name' => $element); $helper[$subPath] =& $parent[$i]; } } print_r($new);
Выход :
Array ( [0] => Array ( [name] => aaa [1] => Array ( [name] => bbb [2] => Array ( [name] => ccc ) ) ) [3] => Array ( [name] => ddd [4] => Array ( [name] => zzz [6] => Array ( [name] => fff ) ) ) [5] => Array ( [name] => zzz ) )
$newarr=array(); foreach ($arr as $element) { $currentroot=$newarr; $pieces=explode('\\', $element); for ($x=0; $x<=count($pieces); x++) { $currentroot[$pieces[$x]]=array(); $currentroot=$currentroot[$pieces[$x]]; } }
Непроверенный, но вам нужно начать. Вам нужно добавить условие, чтобы проверить, является ли это последней частью, и сделать это строковым значением вместо массива.
Ну, пришлось делать это в двух функциях, но здесь идет:
// Directory Array to Hierarchy function _DAtoH($path, $result = null) { if (empty($path)) return array(); if (is_null($result)) $result = array(); $path = explode(DIRECTORY_SEPARATOR, $path); $curr = array_shift($path); if (!isset($result[$curr])) $result[$curr] = array(); $result[$curr] = _DAtoH(implode(DIRECTORY_SEPARATOR, $path), $result[$curr]); return $result; } function DAtoH($arr) { $result = array(); foreach ($arr as $a) $result = _DAtoH($a,$result); return $result; }
Передавая нижнюю функцию (_DAtoH – это всего лишь рекурсивный помощник) массив, указанный вами в исходном вопросе ( var_dump(DAtoH($arr));
), вы должны получить:
array(2) { ["aaa"]=> array(2) { ["bbb"]=> array(1) { ["ccc"]=> array(0) { } } ["fff"]=> array(0) { } } ["ddd"]=> array(1) { ["eee"]=> array(0) { } }
}
(Примечание. Я добавил несколько путей к папкам, чтобы проверить их, таким образом, fff, eee и т. Д.).
Для новых требований:
$arr = array( array('name' => 'aaa'), array('name' => 'aaa\bbb'), array('name' => 'aaa\bbb\ccc'), array('name' => 'ddd'), ); function traverse(array $array) { $mark=array_shift($array); return array($mark => $array ? traverse($array) : array() ); } $out = array(); foreach($arr as $path) { ($add=traverse(explode('\\',$path['name']))) && $out[key($add)]=current($add) ; }
Вывод:
array(2) { ["aaa"]=> array(1) { ["bbb"]=> array(1) { ["ccc"]=> array(0) { } } } ["ddd"]=> array(0) { } }
В старом вопросе были следующие требования:
$arr = array( 0 => 'aaa', 1 => 'aaa\bbb', 2 => 'aaa\bbb\ccc', ); function traverse(array $array) { $mark=array_shift($array); return $array ? array($mark => traverse($array)) : $mark; } $out = array(); foreach($arr as $path) { is_array($add=traverse(explode('\\',$path))) && $out[key($add)]=current($add) ; }
Протестировано, давая этот результат:
array(1) { ["aaa"]=> array(1) { ["bbb"]=> string(3) "ccc" } }