検索ガイド -Search Guide-

単語と単語を空白で区切ることで AND 検索になります。
例: python デコレータ ('python' と 'デコレータ' 両方を含む記事を検索します)
単語の前に '-' を付けることで NOT 検索になります。
例: python -デコレータ ('python' は含むが 'デコレータ' は含まない記事を検索します)
" (ダブルクオート) で語句を囲むことで 完全一致検索になります。
例: "python data" 実装 ('python data' と '実装' 両方を含む記事を検索します。'python data 実装' の検索とは異なります。)
  • ただいまサイドメニューのテスト中/ただいまサイドメニューのテスト中
  • ただいまサイドメニューのテスト中/ただいまサイドメニューのテスト中
  • ただいまサイドメニューのテスト中/ただいまサイドメニューのテスト中
  • ただいまサイドメニューのテスト中/ただいまサイドメニューのテスト中
  • ただいまサイドメニューのテスト中/ただいまサイドメニューのテスト中
  • ただいまサイドメニューのテスト中/ただいまサイドメニューのテスト中
  • ただいまサイドメニューのテスト中/ただいまサイドメニューのテスト中
  • ただいまサイドメニューのテスト中/ただいまサイドメニューのテスト中
  • ただいまサイドメニューのテスト中/ただいまサイドメニューのテスト中
  • ただいまサイドメニューのテスト中/ただいまサイドメニューのテスト中
  • ただいまサイドメニューのテスト中/ただいまサイドメニューのテスト中
>>
python_coding_challenge

【Python 雑談・雑学 + coding challenge】Python の pprint 機能を自分で実装してみよう! 自分なりの Pretty Print できちゃいます!! 投稿一覧へ戻る

Published 2020年8月19日8:17 by mootaro23

SUPPORT UKRAINE

- Your indifference to the act of cruelty can thrive rogue nations like Russia -

Python では pprint モジュールが提供されていて、ネストしているデータ構造を階層的に出力してくれます。


from pprint import pprint


a = [1, 2, 3, 4, 5]
b = [1, [2, [5, 6], 3], 4]


pprint(a, indent=4, width=15)

# [1, 2, 3, 4, 5]




pprint(b, indent=4, width=15)

# [ 1,
# [ 2,
# [5, 6],
# 3],
# 4]




問題 ( 制限時間: 60 分 ):


pprint と同様の機能の実装です ( pprint() を使っちゃダメですよ )。


ただし、実装を簡略化するために、list から成るネスト構造だけを対象にします。


出力は以下の通りです。


a = [1, 2, 3, 4, 5]

my_pretty_print(a)

# [1, 2, 3, 4, 5]




b = [1, [2, [5, 6], 3], 4]

my_pretty_print(b)

# [
# 1,
# [
# 2,
# [5, 6],
# 3
# ],
# 4
# ]




c = [1, 2, [3, 4, [5, 6]]]

my_pretty_print(c)

# [
# 1,
# 2,
# [
# 3,
# 4,
# [5, 6]
# ]
# ]




d = [1, 'Nana', ['Saki', 4, 5, [6, [7, 'Yuka'], 'Hana']], 10, ['Megu', 12]]

my_pretty_print(d)

# [
# 1,
# Nana,
# [
# Saki,
# 4,
# 5,
# [
# 6,
# [7, 'Yuka'],
# Hana
# ]
# ],
# 10,
# ['Megu', 12]
# ]




当たり前ですが、要素を区切るカンマ ',' の位置と数は元の構造と同じでなければなりません。



さていかがだったでしょうか?


今回の実装では list のネスト構造だけを対象にしています。


他のデータ構造が混じっていても対応できるように是非ご自分で進化させてみてください。


以下のように実装してみました。


my_pretty_print() はネストが深くなっていますので、まだまだ改良の余地が多いです。


また、コメントを多めに入れたのでコード本体が見辛くなってます、ご了承ください。


def print_line(item, level, indent=4, suffix=''):
"""
データを出力します

出力するデータの直前に、indent で指定された数のスペースを level で指定された回数だけ繰り返したものを付加します。
(index = 4, level = 2 であればスペースが 4 * 2 = 8 個付加されます。level が 0 のときスペースは付加しません)

出力するデータの直後に、suffix を付加して出力します。

:param item: 出力データ
:param level: 出力データの直前に付加する (indent * スペース) の繰り返し回数
:param indent: インデント数
:param suffix: 出力データの直後に付加する文字列
"""

spaces = '' if level == 0 else (' ' * indent) * level
print(f"{spaces}{item}{suffix}")


def check_iterable_not_str(item):
"""
データがイテラブルであるか判定します。
ただし、イテラブルであっても文字列である場合は False を返します。
(この例題では list だけをターゲットにしていますが、この関数では str 以外のイテラブルであれば True を返しています)
"""

return hasattr(item, '__iter__') and not isinstance(item, str)


def my_pretty_print(seq, level=0, indent=4, suffix=''):
"""
与えられたシーケンスを見やすいように階層表示します。

:param seq: シーケンス。この例題では階層を構成する全てのシーケンスがリストでなければなりません。
:param level: この階層の出力を始めるインデントレベル。level * indent 分のスペースを挿入します。
:param indent: インデント数
:param suffix: この関数に渡されてきたシーケンスの末尾に付加する文字列
"""


# 与えられたデータがシーケンスであるか確認します
if check_iterable_not_str(seq):
# 与えられたシーケンスの中にさらにシーケンスがある場合は「階層表示」します
if [item for item in seq if check_iterable_not_str(item)]: # シーケンス中にシーケンスが存在するかを確認するためだけの list comprehension
print_line('[', level, indent)
for index, item in enumerate(seq, 1):
# 渡されてきたシーケンス内の各要素末尾に付加する文字を設定します
# シーケンス内の最後の要素以外には ',' を付加します
inner_suffix = '' if index == len(seq) else ','

# 要素がシーケンスであれば再帰処理します
if check_iterable_not_str(item):
my_pretty_print(item, level + 1, indent, inner_suffix)
else:
print_line(item, level + 1, indent, inner_suffix)
# このシーケンスの処理の最後に ']' を付加します
# このとき、']' の後に付加する suffix は、このシーケンスを要素として含む 1 つ上の階層内での位置を反映するための、渡されてきた suffix です
print_line(']', level, indent, suffix)
# 与えられたシーケンスが他のシーケンスを含まない場合はそのまま表示します
else:
print_line(seq, level, indent, suffix)
この記事に興味のある方は次の記事にも関心を持っているようです...
- People who read this article may also be interested in following articles ... -
【Python 雑談・雑学 + coding challenge】itertools モジュールの combinations() メソッドを自分で実装してみよう!
【Python 雑談・雑学 + coding challenge】文字列中の数字を抜き出して桁区切りをつけよう! 正規表現 (regular expression ) を使うと「えっ!?」っていうくらい簡単ですょ。lookahead と negative lookahead を使います。
Python coding challenge - 変化球バイナリサーチアルゴリズム (binary search algorithm) を ループ処理 / 再帰処理 の2通りで実装してみよう!
【Python 雑談・雑学 + coding challenge】sorted 組み込み関数の key パラメータをうまく使って、カスタムオブジェクトを簡単にソートしよう! __getitem__、__len__ 特殊関数 ( special methods, dunder methods ) を実装すれば立派なシーケンス ( sequence ) です
【Python 雑談・雑学 + coding challenge】iterator protocol の実装 --- __iter__ 特殊関数は何を返すべき? イテレータオブジェクト ( iterator object ) なら何でも、そう、generator expression でもOKです!
【 Effective Python, 2nd Edition + coding challenge 】プログラム開発のどの段階で並列処理 ( concurrency ) が必要になるのだろう? そのときどのようにリファクタリング ( refactoring ) していけばいいのだろう? を考えてみるシリーズ ( のはず ) 第1回
【Python 雑談・雑学 + coding challenge】Unicode の正規化処理 ( normalization ) を利用して、diacritical marks ( 発音区別符号 ) を取り除こう! テキスト解析の前処理としても重要です!