乱れた台帳を掃除せよ
中段 / 目安 30分
松田さんが眉間にしわを寄せて紙束を差し出してきました。「アルバイトの子が入力した台帳、空白やら『pt』やら混ざっとって…綺麗にしてくれ」。中を見ると " 120pt"、"300 "、"abc" といった調子です。
人が入力した文字列は必ず乱れます。乱れを前提にして、直せるものは直し、直せないものは黙って捨てずに数えて報告する。ここが事務の仕事です。
完成条件
乱れた文字列のリストを受け取り、掃除した結果を返す関数 clean_ledger(rows) を作ってください。
返す値は要素が2つのリストで、次の形にします。
- 1つ目は数値に直せた値を元の並び順のまま並べた整数のリストです
- 2つ目は数値に直せなかった件数の整数です
掃除の規則は次のとおりです。
- 前後の空白は取り除きます
- 末尾や途中に付いた
ptは取り除きます。大文字のPTは取り除きません - 残った文字が空でなく、すべて十進数の数字なら整数に直します。全角数字も受け付けます。符号、小数点、数字の間の空白は数字として扱いません
- 数字にならないものは結果のリストに入れず、件数のほうに1つ数えます。空文字も数字にならないものとして扱います
たとえば [" 120pt", "300 ", "abc"] を渡すと [[120, 300], 1] が返ります。
文字列の道具とリストへの追加
別の題材として、距離の入力を整えます。
Python
raw = " 42km "
text = raw.replace("km", "").strip()
print(text) # "42"
print(text.isdecimal()) # True
lengths = []
lengths.append(int(text))
print(lengths) # [42]replace(消す文字, "") は一致した文字をすべて取り除き、strip() は前後の空白を取り除きます。文字列自体は変わらず、結果の文字列が返るので変数に入れます。"k42km".replace("km", "") は「k42」です。今回の入力整形は補助関数として渡します。
isdecimal() は、空でなくすべて十進数の数字なら True を返します。"42" は真、""、"-4"、"4.2"、"4 2" は偽です。isdigit() は上付きの「²」など整数に直せない文字まで真にするため、ここでは isdecimal を使います。append(値) はリストの末尾に1件を追加します。並び順を保つため、取り出した順に追加します。
進め方
ひな形の「ここに書く」を完成させてください。準備済みのコードはそのまま使えます。手が止まったら、①方針、②使う構文、③部分解の順にヒントを開けます。
数分考えて手が止まったら、①から確認してください。本文の別の題材の例を動かし、今回の値に置き換えて考えましょう。
掃除と判定を1行に詰め込もうとすると、どこで失敗したか分からなくなります。まず整える、次に数字かどうかを見る、最後に振り分ける。3段階に分けて書いてください。
今回は数字だけかを確認してから int に渡します。入力の整形は補助関数に任せ、成功と失敗の振り分けに集中しましょう。
要件
- clean_ledger(rows) は要素が2つのリストを返すこと
- 1つ目の要素は数値に直せた値を元の並び順で並べた整数のリストであること
- 2つ目の要素は数値に直せなかった件数の整数であること
- 準備済みの normalize_point_text で小文字の pt をすべて除き、前後の空白を取り除いてから判定すること
- 数字にならないものと空文字は、リストに入れず件数に数えること
- 残った文字が空でなく、すべて十進数の数字なら int に直すこと。符号・小数点・内部の空白は認めない。全角数字も受け付ける
ヒント
前のヒントを開くと次が開きます。開かずに解けると未開封クリアです