将字符串拆分为数组并追加上一个值

时间:2019-01-25 09:00:51

标签: php arrays explode

我有这个字符串:

  

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中是否已经内置可以解决此问题的东西。

如何通过附加上一个值来构建数组?

6 个答案:

答案 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次迭代的结果(以秒为单位的时间):

enter image description here

这是测试代码。请注意,我已删除了对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

Demo on 3v4l.org