Разбить строку на массив и добавить предыдущее значение - PullRequest
0 голосов
/ 25 января 2019

У меня есть эта строка:

var / log / file.log

В конечном итоге я хочу получить массив, похожий на этот:

Array => [
    '1' => 'var',
    '2' => 'var/log',
    '3' => 'var/log/file.log'
]

В настоящее время у меня есть это:

<code><?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) .'
';

Это кажется действительно нелогичным, и я не уверен, что в PHP уже есть что-то, что могло бы позаботиться об этом.

Как построить массив с помощью добавления предыдущегозначение?

Ответы [ 6 ]

0 голосов
/ 03 февраля 2019

Поскольку я не могу с собой поделать, я сравнил все этих ответов.Ответ @ Yoshi (удален, но вы можете увидеть код ниже) был довольно ясным, затем следовали @OliverNybo (примерно на 15% медленнее), @ pr1nc3 (примерно на 35% медленнее), пробел в шахте и первое и второе @ MaximFedorov.ответ (примерно на 55-75% медленнее), затем еще один пробел в @TimBiegeleisen и, наконец, в последний ответ @ MaximFedorov (который на самом деле не дал правильный результат).Вот результаты для 100 000 итераций (раз в секундах):

enter image description here

Вот код тестирования.Примечание. Я удалил вызов на номер array_reverse, где он использовался, поскольку он не выполняет ничего, кроме изменения порядка вывода.

<code><!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;
}


?>
0 голосов
/ 25 января 2019

Здесь уже есть много хороших ответов, но есть еще один немного другой способ сделать это:

$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

Демонстрация на 3v4l.org

0 голосов
/ 25 января 2019
<?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
)
0 голосов
/ 25 января 2019

В этом решении используется подход, начиная с вашего входного пути, а затем удаляя путь один за другим, добавляя оставшиеся входные данные в массив на каждом шаге. Затем мы обращаем массив в качестве последнего шага, чтобы сгенерировать желаемый результат.

$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 удаляет окончательный путь входной строки, включая косую черту. Это повторяется до тех пор, пока не останется только один конечный компонент пути. Затем мы добавляем этот последний компонент в тот же массив.

0 голосов
/ 25 января 2019

Вы можете получить родительский каталог в цикле и добавить его в переменную 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 
)
0 голосов
/ 25 января 2019

Вы можете сделать что-то подобное с 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 ''. print_r($output, 1) .'
';
...