我有这个字符串:
var / log / 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中是否已经内置可以解决此问题的东西。
如何通过附加上一个值来构建数组?
答案 0 :(得分:11)
<?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
)
答案 1 :(得分:5)
此解决方案采用从输入路径开始,然后一个一个地删除路径,然后在每一步将剩余的输入添加到数组的方法。然后,作为最后一步,我们反转数组以生成所需的输出。
$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
的调用去除了输入字符串的最终路径,包括正斜杠。重复此过程,直到只剩下一个最终路径组件。然后,我们将最后一个组件添加到同一数组中。
答案 2 :(得分:4)
您可以使用foreach做类似的事情
cars = null;
答案 3 :(得分:4)
您可以循环获取父目录,并将其添加到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
字符串作为char数组使用,并在其中查找目录分隔符:
$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
)
答案 4 :(得分:3)
由于我无法自救,因此我对所有这些答案进行了全部基准测试。 @Yoshi的(已删除,但您可以在下面的代码中找到)答案首先很明确,其次是@OliverNybo(慢15%),@ pr1nc3(慢35%),我的差距和@MaximFedorov的第一和第二答案(慢大约55-75%),然后是@TimBiegeleisen的另一个缺口,最后是@MaximFedorov的最后一个答案(实际上并没有返回正确的结果)。以下是100,000次迭代的结果(以秒为单位的时间):
这是测试代码。请注意,我已删除了对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>
答案 5 :(得分:2)
这里已经有很多好的答案,但这是另一种稍微不同的方法:
$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