Подтвердить что ты не робот

Как эхо строк текста вертикально в PHP?

У меня есть эта проблема где-то, и я хочу знать, как ее решить с помощью PHP. С учетом этого текста:

$str = '
PHP is a
widely-used

general-purpose
server side

scripting
language
';

Как отразить текст по вертикали, как показано ниже:

      g        
      e        
      n        
      e        
  w   r s      
  i   a e      
  d   l r   s  
P e   - v   c l
H l   p e   r a
P y   u r   i n
  -   r     p g
i u   p s   t u
s s   o i   i a
  e   s d   n g
a d   e e   g e

В качестве ответа я выберу более простой и элегантный код.

4b9b3361

Ответ 1

Как уже продемонстрировали другие, array_map может выполнять переключение, которое в основном является основной проблемой, которую вам необходимо решить. Остальное - это то, как вы упорядочиваете код. Я думаю, что ваша версия очень хороша, потому что ее легко понять.

Если вы ищете больше других крайностей, обращайтесь с осторожностью:

$str = 'PHP is a
widely-used

general-purpose
server side

scripting
language';

$eol = "\n";
$turned = function($str) use ($eol) {
    $length = max(array_map('strlen', $lines = explode($eol, trim($str))));
    $each = function($a, $s) use ($length) {$a[] = str_split(sprintf("%' {$length}s", $s)); return $a;};
    return implode($eol, array_map(function($v) {return implode(' ', $v);}, call_user_func_array('array_map',
        array_reduce($lines, $each, array(NULL)))));
};

echo $turned($str), $eol;

Дает вам:

      g        
      e        
      n        
      e        
  w   r s      
  i   a e      
  d   l r   s  
P e   - v   c l
H l   p e   r a
P y   u r   i n
  -   r     p g
i u   p s   t u
s s   o i   i a
  e   s d   n g
a d   e e   g e

Это исправляет вывод другого ответа, который был некорректным (теперь он исправлен).

Ответ 2

Приведенный ниже код напечатает $str по вертикали.

$lines = preg_split("/\r\n/", trim($str));
$nl    = count($lines);
$len   = max(array_map('strlen', $lines));

foreach ($lines as $k => $line) {
  $lines[$k] = str_pad($line, $len, ' ', STR_PAD_LEFT);
}

for ($i = 0; $i < $len; $i++) {
  for ($j = 0; $j < $nl; $j++) {
    echo $lines[$j][$i].($j == $nl-1 ? "\n" : " ");
  }
}

Ответ 3

Я взял некоторый код из @bsdnoobz и упростил его. Я использую \n как разрыв строки, потому что я работаю над Mac и \n\n doean здесь.

$lines = preg_split("/\n/", trim($str));
$len   = max(array_map('strlen', $lines));
$rows  = array_fill(0,$len,'');
foreach ($lines as $k => $line) {
    foreach (str_split(str_pad($line, $len, ' ', STR_PAD_LEFT)) as $row => $char){
          $rows[$row] .= $char;
    }
}
echo implode("\n",$rows)."\n";

Ответ 4

$a = explode(PHP_EOL, trim($str));
$h = max(array_map('strlen', $a));
$w = count($a);
$m = array_map('str_split', array_map('sprintf', array_fill(0, $w, "%{$h}s"), $a));
$t = call_user_func_array('array_map', array_merge(array(null), $m));
echo implode(PHP_EOL, array_map('implode', array_fill(0, $h, ' '), $t)), PHP_EOL;

PHP_EOL следует заменить на "\n", "\ r\n" или "< br/ > "; где это необходимо. Весь код после первой строки может легко стать одним большим выражением, только его читаемость немного пострадает; -)

$a - это массив строк, $h - конечная высота, $w - конечная ширина, $m - матрица символов (после заполнения строк), $t - транспонированная матрица.

array_fill(0, $h, ' '), в последней строке можно просто пропустить, если пространство между столбцами не требуется. С другой стороны, не печатать символы пробега пробела могут быть достигнуты следующим образом:

echo implode(PHP_EOL, array_map('rtrim', array_map('implode', array_fill(0, $h, ' '), $t))), PHP_EOL;

Я взял вопрос как упражнение, избегая явных циклов (которые обычно дороже, чем циклы внутри функций PHP, хотя в этом случае преимущество может быть потеряно). Важным трюком здесь является перенос матрицы, который я взял из этого ответа Codler

Во всяком случае, сложность всего алгоритма O(width × height), как и один из большинства алгоритмов на этой странице, за исключением тех, которые многократно объединяют строки для получения строк, сложность которых O(width² × height)

Ответ 5

Я сделаю это:

$arrlines = explode(PHP_EOL, trim($str));
$max = max(array_map('strlen', $arrlines));
foreach($arrlines as $val)
    $arrlines = str_pad($val,$max," ",STR_PAD_LEFT);    
for($x=0;$x<$max;$x++){
    for($y=0;$y<count($arrlines);$y++)
        $string .= strlen(trim($arrlines[$y][$x])) > 0 ? $arrlines[$y][$x]."&nbsp;":"&nbsp;&nbsp;";
    $string .= "\n";
    }
echo '<pre>'.$string.'</pre>';

Номера строк:

  • сохранить строку в строке в массиве $arrlines, разделенном константой PHP PHP_EOL
  • получить максимальную длину строки и сохранить ее до $max
  • для каждого элемента $arrlines, тогда
  • добавьте прописку слева от строки, чтобы ее длина строки равнялась $max

для строк 5-9, вложенный цикл для сохранения $arrline [$ y] [$ x] до $string, а строка 10 выводит результат.

Результат можно найти здесь.

Ответ 6

Вот мой выстрел в него. Не удалось выяснить, как это сделать без вложенного цикла.

$lines = array_map('strrev', explode("\r\n", trim($str)));
$new = array();
foreach(range(0, max(array_map('strlen', $lines))) as $i){ 
    foreach($lines as $line){
        $new[$i] .= (!empty($line[$i]) ? $line[$i] . ' ' : '  ');
    }
}
echo implode("\r\n", (array_slice(array_reverse($new), 1)));

Ответ 7

Моя функция повернуть текст без каких-либо циклов:

/**
 * Rotates text
 *
 * @param string $str String to rotate
 *
 * @return string Rotated string
 */
function rotateText($str)
{
    $lines     = explode(PHP_EOL, $str);
    $lengths   = array_map('strlen', $lines);
    $maxLength = max($lengths);
    $lines     = array_map(function ($line) use ($maxLength) {
        return str_pad($line, $maxLength, ' ', STR_PAD_LEFT);
    }, $lines);
    $chars     = array_map('str_split', $lines);
    array_unshift($chars, null);
    $rotatedLines = call_user_func_array('array_map', $chars);
    $rotatedText  = join(PHP_EOL, array_map('join', $rotatedLines));
    return $rotatedText;
}

echo "<pre>", rotateText($str), "</pre>";

Ответ 8

Обратите внимание, что длина строки и количество элементов в массиве кэшируются по PHP на переменную. Вызов strlen или count повторно имеет только штраф за выполнение пустого вызова функции (при последующих вызовах длина или счет не измеряются дважды внутри PHP).

Это работает с входной строкой Mac (\ r), Linux (\n) или Windows (\ r\n) и/или с пустой строкой ввода и/или с одной строкой ввода строки и выводами с предпочтительным разделителем строк (по умолчанию - PHP_EOL):

function matrix_vertical_align_bottom($str, $strEOL=PHP_EOL)
{
    $arrLines=explode("\n", $str);

    $nMaxLength=max(array_map("strlen", $arrLines));
    $nRotatedWidth=count($arrLines)+strlen($strEOL);

    //allocate once
    $strRotated=str_pad(
        "", 
        $nRotatedWidth*$nMaxLength-strlen($strEOL), 
        str_repeat(" ", count($arrLines)).$strEOL
    );

    foreach($arrLines as $nRotatedColumnIndex=>$strLine)
    {
        $nRotatedVerticalPadding=$nMaxLength-strlen($strLine);
        for($nColumnIndex=strlen($strLine)-1; $nColumnIndex>=0; $nColumnIndex--)
            $strRotated[$nRotatedWidth*($nColumnIndex+$nRotatedVerticalPadding)+$nRotatedColumnIndex]=$strLine[$nColumnIndex];
    }

    return $strRotated;
}

echo matrix_vertical_align_bottom(preg_replace("/(\r\n|\r|\n)/", "\n", trim($str)));

Производительность довольно хороша, вышеперечисленный алгоритм - это просто перевод координат при повороте строки на 90 градусов. Перераспределение памяти не происходит из-за расширения строки, вызванного добавлением отдельных строк (для строк ввода с большим количеством строк это будет хитом производительности).

Выход HTML не предполагается, nl2br (htmlspecialchars()), когда вывод должен делать трюк + шрифт с разнесением моно.

Ответ 9

Вот простой код, который может понять этот код

    $str = '
    PHP is a
    widely-used

    general-purpose
    server side

    scripting
    language
    ';

    $lines = array();

    $sentences = explode("\n\n",$str);
    foreach($sentences as $sentence){
        if($sentence != ""){
            $each_lines = explode("\n",$sentence);
            foreach($each_lines as $each_line){
                if($each_line != ""){
                    $lines[] = $each_line;
                }
            }
            $lines[] = "\t";
        }
    }
    $before_sort = $lines;
    usort($lines, "cmp_len");
    $big_length = strlen($lines[0]);
    foreach($before_sort as $key=>$arr){
        $this_length = strlen($arr);
        if($this_length < $big_length){
            $no_of_letters = $big_length - $this_length;
            $text = "";
            for($i=0;$i<$no_of_letters;$i++){
                $text .= " ";
            }
            $text .= $before_sort[$key];
            $before_sort[$key] = $text;
        }
    }

    $temp = array();
    echo "<table>";
    for($i=0;$i<$big_length;$i++){
      echo "<tr>";
        foreach($before_sort as $arr){
            echo "<td>";
                echo str_replace("\t","&nbsp;&nbsp;&nbsp;&nbsp;",$arr[$i]);
            echo "</td>";
        }
      echo "</tr>";
    }
    echo "</table>";





    function cmp_len($a, $b){
       return (strlen($a)  < strlen($b));
    }

Ответ 10

Отметьте этот ответ:

<?php

$str = 'PHP is a
widely-used

general-purpose
server side

scripting
language';


function getVerticalString($str){
    $str = preg_split('/\r|\n/',$str);

    $maxlength = 0;

    $totalstr = count($str);

    for($i=0;$i<$totalstr;$i++){
        if($maxlength<strlen($str[$i])){
            $maxlength = strlen($str[$i]);
        }
    }

    $strings = array();

    for($i=0;$i<$maxlength;$i++){
        $strings[$i] = "";
        for($j=0;$j<$totalstr;$j++){
            $temp = strlen($str[$j])-($maxlength-$i);
            if($temp>=0){
                $strings[$i] .= substr($str[$j],$temp,1);
            }
            else{
                $strings[$i] .= " ";
            }
        }
    }

    return implode("\r",$strings);
}

echo "<pre>".getVerticalString($str)."</pre>";

эти выходы:

   g    
   e    
   n    
   e    
 w rs   
 i ae   
 d lr s 
Pe -v cl
Hl pe ra
Py ur in
 - r  pg
iu ps tu
ss oi ia
 e sd ng
ad ee ge

В соответствии с вашими требованиями.:)

Ответ 11

Я бы не назвал его короче, но количество строк меньше: -)

$nr_lines = count($lines = preg_split('/\r?\n/', trim($str)));
$maxlen = max($lengths = array_map('strlen', $lines)); // get line lengthts and maximum
$line_ptrs = array_fill(0, $nr_lines, 0); // last character position per line

for ($j = 0; $j != $maxlen; ++$j) {
    for ($i = 0; $i != $nr_lines; ++$i) {
        // $maxlen - $lengths[$i] indicates where printing start for this line
        echo $j >= $maxlen - $lengths[$i] ? $lines[$i][$line_ptrs[$i]++] : ' ';
    }
    echo "\n";
}

Он заполняет и печатает в том же внутреннем цикле, которому помогают массивы $line_ptrs и $lengths, чтобы отслеживать, какой символ печатать дальше.

Benchmark

На основе 10000 итераций этот код выполняет на 19% лучше, чем первый ответ.

Ответ 12

Попробуйте это,

$str = 'PHP is a
widely-used

general-purpose
server side

scripting
language';

$strArr = explode("\r\n", $str);
$max =max(array_map('strlen', $strArr));

for($i=0; $i< $max;$i++)
{
    for($x=0;$x < count($strArr); $x++)
    {
        $strVal = $strArr[$x];
        $y = $i -($max -  strlen($strVal));
        $vertical .= strlen(trim($strVal[$y]))<> 0 ? $strVal[$y]." " : "  ";
    } 
    $vertical .="\n";
}
echo "<pre>".$vertical;

Ответ 13

Самый лучший и простой способ:)

<style type="text/css">
#heading{
    /* vertical text css */
    width:1em;
    text-transform:uppercase;
}
</style>

<h1 align="center" id="heading">h e l l o</h1>

DEMO

Ответ 14

$a= 'HelloWorld!';
$b=strlen($a);
for($i=0;$i<$b;$i++){
echo $c=substr($a,$i,1).'<br>';  
}