分割字符串到数组和附加上一个值

问题描述 投票:14回答:6

我有这个字符串:

无功/日志/ 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能够照顾这。

如何构建使用追加前值的阵列?

php arrays explode
6个回答
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剥掉输入字符串的最后路径,包括斜线。这被重复,直到有只留下最后一个路径组件。然后,我们去年组件添加到同一阵列。


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
)

4
投票

你可以做这样的事情在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>';

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字符串作为工作的字符数组,并发现它的目录分隔符:

$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 
)

3
投票

因为我不能帮助我自己,我为基准所有这些答案。 @ Yoshi的(删除,但你可以看到下面的代码),答案出来了相当明确的首位,其次是@OliverNybo(大约慢15%),@ pr1nc3(约35%的速度较慢),矿山和@ MaximFedorov的第一和第二差距答案(慢约55-75%),然后另一个差距@TimBiegeleisen终于@ MaximFedorov最后的答案(这实际上并没有返回正确的结果)。这里有10万次迭代(以秒为时间)的结果:

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>

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

© www.soinside.com 2019 - 2024. All rights reserved.