横書きの文章を縦書きに変換してTwitterなどに投稿したい

Twitterなど、ほぼ全てのSNSは横書きですね。Pythonプログラミングの勉強も兼ねて、これを縦書きに変換するPythonスクリプトを書いてみましょう。

# Tweet

以下のツイートを縦書きにしてみたいと思います。

```python
tweet = '''\
普通は Tweet は横書きなんだけどさ、
これを縦書きにしたいわけよ。
そうすると、検索されにくくなるんじゃね？
いっちょ Pythonでやってみないか？
'''
```


```python
tweet
```




    '普通は Tweet は横書きなんだけどさ、\nこれを縦書きにしたいわけよ。\nそうすると、検索されにくくなるんじゃね？\nいっちょ Pythonでやってみないか？\n'


# １文字１文字に分解

次のようにすれば１文字１文字に分解できます。

```python
for line in tweet.split("\n"):
    print([line[i] for i in range(len(line))])
```

    ['普', '通', 'は', ' ', 'T', 'w', 'e', 'e', 't', ' ', 'は', '横', '書', 'き', 'な', 'ん', 'だ', 'け', 'ど', 'さ', '、']
    ['こ', 'れ', 'を', '縦', '書', 'き', 'に', 'し', 'た', 'い', 'わ', 'け', 'よ', '。']
    ['そ', 'う', 'す', 'る', 'と', '、', '検', '索', 'さ', 'れ', 'に', 'く', 'く', 'な', 'る', 'ん', 'じ', 'ゃ', 'ね', '？']
    ['い', 'っ', 'ち', 'ょ', ' ', 'P', 'y', 't', 'h', 'o', 'n', 'で', 'や', 'っ', 'て', 'み', 'な', 'い', 'か', '？']
    []

ただし、最後の行だけ空白行になってしまうので除外しましょう。

```python
for line in tweet.split("\n"):
    if len(line) > 0:
        print([line[i] for i in range(len(line))])
```

    ['普', '通', 'は', ' ', 'T', 'w', 'e', 'e', 't', ' ', 'は', '横', '書', 'き', 'な', 'ん', 'だ', 'け', 'ど', 'さ', '、']
    ['こ', 'れ', 'を', '縦', '書', 'き', 'に', 'し', 'た', 'い', 'わ', 'け', 'よ', '。']
    ['そ', 'う', 'す', 'る', 'と', '、', '検', '索', 'さ', 'れ', 'に', 'く', 'く', 'な', 'る', 'ん', 'じ', 'ゃ', 'ね', '？']
    ['い', 'っ', 'ち', 'ょ', ' ', 'P', 'y', 't', 'h', 'o', 'n', 'で', 'や', 'っ', 'て', 'み', 'な', 'い', 'か', '？']


以上の処理を、リスト内包表記を使ってスマートに表現し、 `data` という変数に入れます。

```python
data = [[line[i] for i in range(len(line))] for line in tweet.split("\n") if len(line) > 0]
print(data)
```

    [['普', '通', 'は', ' ', 'T', 'w', 'e', 'e', 't', ' ', 'は', '横', '書', 'き', 'な', 'ん', 'だ', 'け', 'ど', 'さ', '、'], ['こ', 'れ', 'を', '縦', '書', 'き', 'に', 'し', 'た', 'い', 'わ', 'け', 'よ', '。'], ['そ', 'う', 'す', 'る', 'と', '、', '検', '索', 'さ', 'れ', 'に', 'く', 'く', 'な', 'る', 'ん', 'じ', 'ゃ', 'ね', '？'], ['い', 'っ', 'ち', 'ょ', ' ', 'P', 'y', 't', 'h', 'o', 'n', 'で', 'や', 'っ', 'て', 'み', 'な', 'い', 'か', '？']]


# numpy で転置

行列の転置したいので  numpy が使えるといいのですが

```python
import numpy as np
np.array(data)
```




    array([list(['普', '通', 'は', ' ', 'T', 'w', 'e', 'e', 't', ' ', 'は', '横', '書', 'き', 'な', 'ん', 'だ', 'け', 'ど', 'さ', '、']),
           list(['こ', 'れ', 'を', '縦', '書', 'き', 'に', 'し', 'た', 'い', 'わ', 'け', 'よ', '。']),
           list(['そ', 'う', 'す', 'る', 'と', '、', '検', '索', 'さ', 'れ', 'に', 'く', 'く', 'な', 'る', 'ん', 'じ', 'ゃ', 'ね', '？']),
           list(['い', 'っ', 'ち', 'ょ', ' ', 'P', 'y', 't', 'h', 'o', 'n', 'で', 'や', 'っ', 'て', 'み', 'な', 'い', 'か', '？'])],
          dtype=object)


以上のように、リストのアレイになってしまい、うまくいきません。

そこで、行数と列数をしっかり測って、その大きさに相当する配列を用意しましょう。

```python
max_length = 0 # 最も長い文の文字数を数える
for d in data:
    if max_length < len(d):
        max_length = len(d)
```

以上のようにすれば、 `tweet` は `len(data)` 行 `max_length` 列の配列で表現できることが分かります。そこで、同じ大きさの numpy 配列を用意しましょう。あらかじめ空白文字で埋めておきます。


```python
import numpy as np
np.full((len(data), max_length), "　")
```




    array([['\u3000', '\u3000', '\u3000', '\u3000', '\u3000', '\u3000',
            '\u3000', '\u3000', '\u3000', '\u3000', '\u3000', '\u3000',
            '\u3000', '\u3000', '\u3000', '\u3000', '\u3000', '\u3000',
            '\u3000', '\u3000', '\u3000'],
           ['\u3000', '\u3000', '\u3000', '\u3000', '\u3000', '\u3000',
            '\u3000', '\u3000', '\u3000', '\u3000', '\u3000', '\u3000',
            '\u3000', '\u3000', '\u3000', '\u3000', '\u3000', '\u3000',
            '\u3000', '\u3000', '\u3000'],
           ['\u3000', '\u3000', '\u3000', '\u3000', '\u3000', '\u3000',
            '\u3000', '\u3000', '\u3000', '\u3000', '\u3000', '\u3000',
            '\u3000', '\u3000', '\u3000', '\u3000', '\u3000', '\u3000',
            '\u3000', '\u3000', '\u3000'],
           ['\u3000', '\u3000', '\u3000', '\u3000', '\u3000', '\u3000',
            '\u3000', '\u3000', '\u3000', '\u3000', '\u3000', '\u3000',
            '\u3000', '\u3000', '\u3000', '\u3000', '\u3000', '\u3000',
            '\u3000', '\u3000', '\u3000']], dtype='<U1')


あとは、その numpy array に data の文字を１文字１文字書き写します。

ただし、このとき、文の順序が逆になるようにします。

```python
data2 = np.full((len(data), max_length), "　")
for i in range(len(data)):
    for j in range(max_length):
        if j < len(data[i]):
            data2[len(data) - i - 1][j] = data[i][j]
data2
```




    array([['い', 'っ', 'ち', 'ょ', ' ', 'P', 'y', 't', 'h', 'o', 'n', 'で', 'や',
            'っ', 'て', 'み', 'な', 'い', 'か', '？', '\u3000'],
           ['そ', 'う', 'す', 'る', 'と', '、', '検', '索', 'さ', 'れ', 'に', 'く', 'く',
            'な', 'る', 'ん', 'じ', 'ゃ', 'ね', '？', '\u3000'],
           ['こ', 'れ', 'を', '縦', '書', 'き', 'に', 'し', 'た', 'い', 'わ', 'け', 'よ',
            '。', '\u3000', '\u3000', '\u3000', '\u3000', '\u3000', '\u3000',
            '\u3000'],
           ['普', '通', 'は', ' ', 'T', 'w', 'e', 'e', 't', ' ', 'は', '横', '書',
            'き', 'な', 'ん', 'だ', 'け', 'ど', 'さ', '、']], dtype='<U1')


ここまでできれば、行列の転置を用いて縦書きにできます。

```python
data2.T # 行列の転置
```




    array([['い', 'そ', 'こ', '普'],
           ['っ', 'う', 'れ', '通'],
           ['ち', 'す', 'を', 'は'],
           ['ょ', 'る', '縦', ' '],
           [' ', 'と', '書', 'T'],
           ['P', '、', 'き', 'w'],
           ['y', '検', 'に', 'e'],
           ['t', '索', 'し', 'e'],
           ['h', 'さ', 'た', 't'],
           ['o', 'れ', 'い', ' '],
           ['n', 'に', 'わ', 'は'],
           ['で', 'く', 'け', '横'],
           ['や', 'く', 'よ', '書'],
           ['っ', 'な', '。', 'き'],
           ['て', 'る', '\u3000', 'な'],
           ['み', 'ん', '\u3000', 'ん'],
           ['な', 'じ', '\u3000', 'だ'],
           ['い', 'ゃ', '\u3000', 'け'],
           ['か', 'ね', '\u3000', 'ど'],
           ['？', '？', '\u3000', 'さ'],
           ['\u3000', '\u3000', '\u3000', '、']], dtype='<U1')


転置した行列を文字列として出力

```python
delimiter = " "
for line in data2.T:
    print(delimiter.join(line))
```

    い そ こ 普
    っ う れ 通
    ち す を は
    ょ る 縦  
      と 書 T
    P 、 き w
    y 検 に e
    t 索 し e
    h さ た t
    o れ い  
    n に わ は
    で く け 横
    や く よ 書
    っ な 。 き
    て る 　 な
    み ん 　 ん
    な じ 　 だ
    い ゃ 　 け
    か ね 　 ど
    ？ ？ 　 さ
    　 　 　 、

これを、リスト内包表記を使ってスマートに書き直せばこうなります。

```python
delimiter = " "
print("\n".join([delimiter.join(line) for line in data2.T]))
```

    い そ こ 普
    っ う れ 通
    ち す を は
    ょ る 縦  
      と 書 T
    P 、 き w
    y 検 に e
    t 索 し e
    h さ た t
    o れ い  
    n に わ は
    で く け 横
    や く よ 書
    っ な 。 き
    て る 　 な
    み ん 　 ん
    な じ 　 だ
    い ゃ 　 け
    か ね 　 ど
    ？ ？ 　 さ
    　 　 　 、

# まとめ

以上の操作を `yoko2tate` という関数にしてみました。

```python
def yoko2tate(tweet, delimiter = " "):
    data = [[line[i] for i in range(len(line))] for line in tweet.split("\n") if len(line) > 0]
    max_length = 0
    for d in data:
        if max_length < len(d):
            max_length = len(d)
    data2 = np.full((len(data), max_length), "　")
    for i in range(len(data)):
        for j in range(max_length):
            if j < len(data[i]):
                data2[len(data) - i - 1][j] = data[i][j]
    return "\n".join([delimiter.join(line) for line in data2.T])
```

使用例はこんな感じ。

```python
tweet = '''\
あ...ありのまま 今 起こったことを話すぜ！

「ツイートを入力したら、縦書きになった」

な...何を言っているか分からねーと思うが、おれも何をされたのか分からなかった...
'''

print(yoko2tate(tweet))
```

    な 「 あ
    . ツ .
    . イ .
    . ー .
    何 ト あ
    を を り
    言 入 の
    っ 力 ま
    て し ま
    い た  
    る ら 今
    か 、  
    分 縦 起
    か 書 こ
    ら き っ
    ね に た
    ー な こ
    と っ と
    思 た を
    う 」 話
    が 　 す
    、 　 ぜ
    お 　 ！
    れ 　 　
    も 　 　
    何 　 　
    を 　 　
    さ 　 　
    れ 　 　
    た 　 　
    の 　 　
    か 　 　
    分 　 　
    か 　 　
    ら 　 　
    な 　 　
    か 　 　
    っ 　 　
    た 　 　
    . 　 　
    . 　 　
    .