我有这个字符串:
无功/日志/ file.log
我最终想要一个数组看起来像这样结束了:
Array => [
'1' => 'var',
'2' => 'var/log',
'3' => 'var/log/file.log'
]
我现在有这样的:
<?php
$string = 'var/log/file.log';
$array = explode('/', $string);
$output = [
1 => $array[0],
2 => $array[0]. '/' .$array[1],
3 => $array[0]. '/' .$array[1]. '/' .$array[2]
];
echo '<pre>'. print_r($output, 1) .'</pre>';
这种感觉真的反直觉的,我不知道是否有一些已经内置到PHP能够照顾这。
如何构建使用追加前值的阵列?
该解决方案需要与您的输入路径开始,然后由一个除去一个路径中的一个,将所述剩余输入到在每一个步骤的阵列的方法。然后,我们扭转数组作为最后一步,产生你想要的输出。
$input = "var/log/file.log";
$array = [];
while (preg_match("/\//i", $input)) {
array_push($array, $input);
$input = preg_replace("/\/[^\/]+$/", "", $input);
echo $input;
}
array_push($array, $input);
$array = array_reverse($array);
print_r($array);
Array
(
[0] => var
[1] => var/log
[2] => var/log/file.log
)
上述呼叫到preg_replace
剥掉输入字符串的最后路径,包括斜线。这被重复,直到有只留下最后一个路径组件。然后,我们去年组件添加到同一阵列。
<?php
$string = 'var/log/some/other/directory/file.log';
$array = explode('/', $string);
$i = 0;
foreach ($array as $data) {
$output[] = isset($output) ? $output[$i - 1] . '/' . $data : $data;
$i++;
}
echo '<pre>';
print_r($output);
一种更简单的解决方案是上面。您简单的设置你的新阵列领域是你的前一个从你新的数组并从foreach
当前一个的串联。
输出是:
Array
(
[0] => var
[1] => var/log
[2] => var/log/some
[3] => var/log/some/other
[4] => var/log/some/other/directory
[5] => var/log/some/other/directory/file.log
)
你可以做这样的事情在foreach
<?php
$string = 'var/log/file.log';
$array = explode('/', $string);
$last = '';
$output = array();
foreach ($array as $key => $value) {
$result = $last.$value;
$output[$key] = $result;
$last = $result.'/';
}
echo '<pre>'. print_r($output, 1) .'</pre>';
您可以在一个循环中获取父目录,并把它添加到output
变量。例如与帮助下面的算法:
$path = 'var/log/file.log';
$output = [];
$pos = strlen($path);
while ($pos !== false) {
$path = substr($path, 0, $pos);
array_unshift($output, $path);
$pos = strrpos($path, DIRECTORY_SEPARATOR);
}
或dirname()
功能
$path = 'var/log/file.log';
$output = [];
do {
array_unshift($output, $path);
$path = dirname($path);
} while ($path !== '.');
此外,您还可以使用$path
字符串作为工作的字符数组,并发现它的目录分隔符:
$path = 'var/log/file.log';
$output = [];
$tmp = '';
$len = strrpos($path, DIRECTORY_SEPARATOR); // you can use strlen instead of strrpos,
// but it'll look over filename also
for ($i = 0; $i < $len; $i++) {
if ($path[$i] === DIRECTORY_SEPARATOR) {
$output[] = $tmp;
}
$tmp .= $path[$i];
}
$output[] = $path;
但请记住,你不能用这种方式,如果$path
字符串具有多字节编码
所有方法的结果将是:
Array (
[0] => var
[1] => var/log
[2] => var/log/file.log
)
因为我不能帮助我自己,我为基准所有这些答案。 @ Yoshi的(删除,但你可以看到下面的代码),答案出来了相当明确的首位,其次是@OliverNybo(大约慢15%),@ pr1nc3(约35%的速度较慢),矿山和@ MaximFedorov的第一和第二差距答案(慢约55-75%),然后另一个差距@TimBiegeleisen终于@ MaximFedorov最后的答案(这实际上并没有返回正确的结果)。这里有10万次迭代(以秒为时间)的结果:
下面是测试代码。请注意我已经删除调用array_reverse
它被使用,因为它不会做的比改变输出顺序的任何其他。
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
table {
border-collapse: collapse;align-content:
}
td, th {
border: 1px solid black;
padding: 5px;
}
</style>
</head>
<body>
<pre>
<?php
$string = 'var/log/some/other/directory/file.log';
$elapsed = array();
foreach (array('TimBiegeleisen', 'pr1nc3', 'OliverNybo', 'MaximFedorov1', 'MaximFedorov2', 'MaximFedorov3', 'Nick') as $func) {
$start = explode(' ', microtime());
for ($i = 0; $i < 100000; $i++) $func($string);
$elapsed[$func] = elapsed_time($start);
}
asort($elapsed);
$fastest = min($elapsed);
echo "<table><tr><th>Function</th><th>Elapsed Time</th><th>Delta</tr>";
foreach ($elapsed as $key => $value) {
echo "<td>$key</td><td>$value</td>";
echo "<td>" . sprintf("%.0f%%", ($value - $fastest) / $fastest * 100) . "</td></tr>";
}
echo "</table>\n";
function TimBiegeleisen($input) {
$array = [];
while (preg_match("/\//i", $input)) {
array_push($array, $input);
$input = preg_replace("/\/[^\/]+$/", "", $input);
}
array_push($array, $input);
return $array;
// return array_reverse($array);
}
function pr1nc3($string) {
$array = explode('/', $string);
$i = 0;
foreach ($array as $data) {
$output[] = isset($output) ? $output[$i - 1] . '/' . $data : $data;
$i++;
}
return $output;
}
function OliverNybo($string) {
$array = explode('/', $string);
$last = '';
$output = array();
foreach ($array as $key => $value) {
$result = $last.$value;
$output[$key] = $result;
$last = $result.'/';
}
return $output;
}
function MaximFedorov1($path) {
$output = [];
$pos = strlen($path);
while ($pos !== false) {
$path = substr($path, 0, $pos);
array_unshift($output, $path);
$pos = strrpos($path, '/');
}
return $output;
}
function MaximFedorov2($path) {
$output = [];
do {
array_unshift($output, $path);
$path = dirname($path);
} while ($path !== '.');
return $output;
}
function MaximFedorov3($path) {
$output = [];
$tmp = '';
$len = strrpos($path, '/'); // you can use strlen instead of strrpos,
// but it'll look over filename also
for ($i = 0; $i < $len; $i++) {
if ($path[$i] === '/') {
$output[] = $tmp;
}
$tmp .= $path[$i];
}
$output[] = $path;
return $output;
}
function Nick($string) {
$array = explode('/', $string);
for ($c = count($array); $c > 0; ) {
$output[--$c] = implode('/', $array);
array_pop($array);
}
return $output;
// return array_reverse($output)
}
function Yoshi($input) {
$output = explode('/', $input);
for ($i = 1, $lim = \count($output); $i < $lim; $i++) {
$output[$i] = $output[$i - 1] . '/' . $output[$i];
}
return $output;
}
function elapsed_time(array $start) {
$now = explode(' ', microtime());
$deltasec = $now[1] - $start[1];
$deltamsec = (float)$now[0] - (float)$start[0];
return $deltasec + $deltamsec;
}
?>
</pre>
</body>
</html>
有很多在这里已经很好的答案,但这里是这样做的另一种略有不同的方式:
$string = 'var/log/some/other/directory/file.log';
$array = explode('/', $string);
for ($c = count($array); $c > 0; ) {
$output[--$c] = implode('/', $array);
array_pop($array);
}
for ($i = 0; $i < count($output); $i++) {
echo "$output[$i]\n";
}
输出:
var
var/log
var/log/some
var/log/some/other
var/log/some/other/directory
var/log/some/other/directory/file.log