vaguely

和歌山に戻りました。ふらふらと色々なものに手を出す毎日。

【C#】横書き -> 縦書き変換

はじめに

Twitterにてちょっと話題になった、テキストを縦書きで投稿するためのメモです。

今回はテキストを固定にしていますが、Unity、WPFなどで入力元、出力先を指定してやれば動的に生成したり、
Twitterなどにそのまま投稿することもできます。

縦に書く

TextViewなどの機能を使う場合は別ですが、
文字列を縦に並べるには単純に文字列を一文字ずつに区切って、それを縦に並ぶよう置き換えるのが良さそうです。

なお列の区切りは改行文字とします。

まずは一文字ずつに区切り、ついでに全角・半角文字が混ざると位置がずれてしまうので、半角文字の場合はスペースを追加することにします。

// 元のテキスト.
const string sampleText = "Hello\nworld\nおはようございます!\n";
// 改行文字で区切る.
var splittedSamples = sampleText.Split('\n');

// ToCharArray()で一文字ずつ切り出し -> charからstringに戻す -> 半角文字にスペース追加.
var results = splittedSamples.ToList()
    .Select(samples => samples.ToCharArray()
        .Select(sample => sample.ToString())
        .Select(sample => Regex.Replace(sample, @"[a-zA-Z0-9|\.\-\\\,]", " " + sample))
        .ToList()).ToList();

これで一文字ずつ切り出して、一行ずつにまとめた List< List< string>> の値となります。

なお、長音の縦横置き換えなどは行っていないため、必要に応じて追加してください。

あとはこれを頭から並べていきます。

const string sampleText = "Hello\nworld\naaa\nbbb\n";
            
var splittedSamples = sampleText.Split('\n');

var results = splittedSamples.ToList()
    .Select(samples => samples.ToCharArray()
        .Select(sample => sample.ToString())
        .Select(sample => Regex.Replace(sample, @"[a-zA-Z0-9|\.\-\\\,]", " " + sample))
        .ToList()).ToList();

var resultMaxCount = results.Select(samples => samples.Count).Max();

var resultText = "\n";
for (var i = 0; i < resultMaxCount; i++)
{
    for (var j = results.Count - 1; j >= 0; j--)
    {
        // 列の間に全角スペースをはさむ.
        resultText += "  ";
        // その列に文字がなかった場合は全角スペースに置き換え.
        resultText += (results[j].Count - 1 >= i) ? results[j][i] : "  ";
    }
    resultText += "\n";
}

せっかくなのでこちらも Linq で解決したいところでしたが、
良い方法が思いつかなかったのでfor文を使うことにしました。

また、Twitterに投稿する場合に、一行目の最初の文字より前に入っているスペースが取り除かれてしまうようです。
それを防ぐため、頭に改行を挟んでいます。

参考