How to group elements of array?
I've an array of folders/paths:
$arr = Array
(
0 => Array
(
'name' => 'aaa'
),
1 => Array
(
'name' => 'aaa\bbb'
),
2 => Array
(
'name' => 'aaa\bbb\ccc'
),
3 => Array
(
开发者_StackOverflow 'name' => 'ddd'
)
);
I'd like to transform it to multidimensional (tree-like) array (keeping the structure: index/key & value/name):
aaa
bbb
ccc
ddd
Any suggests?
Try:
$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);
Output:
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]];
}
}
Untested but should get you started. You need to add a condition to check if it is the last piece, and make it a string value instead of an array.
Well, had to do it in two functions, but here goes:
// 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;
}
Passing the bottom function (the _DAtoH is just a recursive helper) the array you specified in your original question (var_dump(DAtoH($arr));
), you should receive:
array(2) {
["aaa"]=>
array(2) {
["bbb"]=>
array(1) {
["ccc"]=>
array(0) {
}
}
["fff"]=>
array(0) {
}
}
["ddd"]=>
array(1) {
["eee"]=>
array(0) {
}
}
}
(Note: I added some folder paths just to test it out, thus the fff, eee, etc.)
For the new requirements:
$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)
;
}
Output:
array(2) {
["aaa"]=>
array(1) {
["bbb"]=>
array(1) {
["ccc"]=>
array(0) {
}
}
}
["ddd"]=>
array(0) {
}
}
Old Question:
The old question had these reqs:
$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)
;
}
Tested, giving this output:
array(1) {
["aaa"]=>
array(1) {
["bbb"]=>
string(3) "ccc"
}
}
精彩评论