使用PHP 5.2,我试图将任意数量的路径/目录字符串解析为一个数组,这样就可以先处理广度。这是为了让我能够从Subversion存储库中编写稀疏签出的脚本,伸缩指示的路径。必须在同一svn update --depth empty
语句中指定同一级别上的所有路径。
我得到了想要的输出,但我想知道是否有更干净的方法。(是的,我知道效率需要改变。)
EDIT我修改了原来的帖子,以处理同一父级中多个子级的情况。我修改后的代码是
$main = array(
'a/b/c1/',
'a/b/c2/d/e1',
'a/b/c2/d/e2',
'A/B/',
'alpha/beta/gamma/delta/epsilon'
);
$splits = array();
$max = 0;
for ($i=0; $i<count($main); $i++) {
$splits[$i] = explode(DIRECTORY_SEPARATOR, trim($main[$i], DIRECTORY_SEPARATOR));
if (count($splits[$i]) > $max) {
$max = count($splits[$i]);
}
}
for ($i=0; $i<$max; $i++) {
$levels[$i] = array();
for ($path=0; $path<count($splits); $path++) {
if (array_key_exists($i, $splits[$path])) {
$levels[$i][] = implode(DIRECTORY_SEPARATOR, array_slice($splits[$path], 0, $i+1));
}
}
$levels[$i] = array_unique($levels[$i]);
sort($levels[$i]); // just to reset indices
}
这将我的输出结构更改为以下结构,既在每个级别提供了唯一的目录,又保留了同级节点。
Array
(
[0] => Array
(
[0] => A
[1] => a
[2] => alpha
)
[1] => Array
(
[0] => A/B
[1] => a/b
[2] => alpha/beta
)
[2] => Array
(
[0] => a/b/c1
[1] => a/b/c2
[2] => alpha/beta/gamma
)
[3] => Array
(
[0] => a/b/c2/d
[1] => alpha/beta/gamma/delta
)
[4] => Array
(
[0] => a/b/c2/d/e1
[1] => a/b/c2/d/e2
[2] => alpha/beta/gamma/delta/epsilon
)
)
在我的代码中,我对最终的$levels
数组进行迭代。不幸的是,这仍然需要两次迭代:一次用于depth empty
,一次用于depth infinity
,但我相信这是可以实现的。
$count = count($levels);
for ($i=0; $i<$count; $i++) {
echo '<p>', 'svn update --set-depth empty ', implode(' ', $levels[$i]), "</p>'n";
}
$count = count($main);
for ($i=0; $i<$count; $i++) {
echo '<p>', 'svn update --set-depth infinity ', $main[$i], "</p>'n";
}
$levels=array();
$depth=0;
$i=0;
foreach ($main as $m) {
$m=explode('/',$m);
while (sizeof($m)<$depth) $m[]=null;
$d=0;
foreach ($m as $mm) {
if ($d>$depth) {
if (!$mm) break;
$depth=$d;
$levels[$d]=array();
for ($j=0;$j<=$i;$j++) $levels[$d][$j]=null;
}
$levels[$d][$i]=$mm;
$d++;
}
$i++;
}
看起来是一个很好的选择,只需要遍历一次数组。简言之,您不使用一次传递来决定深度,但如果遇到更深的条目,您只需用null追溯填充数组中的相关位置。
$depth在循环之后具有depth-1。
编辑:
这还可以处理同一个父级中有多个子级的情况,但我不确定它是否按照您想要的方式来处理
以下是我的实现(随着您的最新请求,它变得更容易了):
$levels = array();
for ($i=0; $i<count($main); $i++) {
$splits = explode(DIRECTORY_SEPARATOR, trim($main[$i], DIRECTORY_SEPARATOR));
$current = array();
/* Load every subpath in an array*/
for($j=0; $j<count($splits); $j++) {
$current[$j . "hack"] = implode("/", array_slice($splits, 0, $j+1));
}
$levels = array_merge_recursive($levels, $current);
}
/* Removes duplicates and resets indices */
array_walk($levels, function(&$l, $i) { $l = array_unique($l); sort($l); });
这个实现之所以简单,是因为我分别处理每个路径。我只有一个循环,并使用array_merge_recursive
连接结果。例如,对于"a/b"answers"a/c",我的代码是:
- 创建
array(0 => array("a"), 1 => array("a/b"))
和array(0 => array("a"), 1 => array("a/c"))
- 将它们与
array_merge_recursive
结合,从而得到array(0 => array("a", "a"), 1 => array("a/b", "a/c"))
- 使用
array_unique
删除唯一值 - 用
sort
重置索引
注意:我需要使用$j + "hack"
,否则array_merge_recursive
不会按预期合并值(自己试试)。