Pythonで文字列を扱っていると、1文字ずつ取り出して処理したい場面が出てきます。文字の出現回数のカウント、特定の文字の検索・置換、文字列の暗号化処理など、文字列を1文字ずつ処理する操作はPythonの文字列処理の基本スキルのひとつです。
Pythonの文字列はイテラブルなオブジェクトのため、forループで直接1文字ずつ取り出せます。またenumerate()との組み合わせで位置情報も同時に取得でき、リスト内包表記を使えばシンプルなコードで柔軟な文字列処理が実現できます。
この記事では、Pythonで文字列を1文字ずつ処理する方法を、forループの基本・enumerate()との組み合わせ・リスト内包表記・応用パターンまで、サンプルコードとともにわかりやすく解説していきます。
Pythonで文字列を1文字ずつ処理するにはforループが最もシンプルな方法
それではまず、Pythonで文字列を1文字ずつ処理する基本的な方法について解説していきます。
Pythonの文字列はイテラブルなオブジェクトのため、forループに文字列を直接渡すだけで1文字ずつ取り出せます。特別なメソッドを使わずに直感的に書けるのが大きな特徴です。
# forループで文字列を1文字ずつ処理
text = "gorilla"
for char in text:
print(char)
# 出力結果:g
# 出力結果:o
# 出力結果:r
# 出力結果:i
# 出力結果:l
# 出力結果:l
# 出力結果:a
forループで文字列をイテレートすると、先頭から1文字ずつ変数に代入されて処理が進みます。非常にシンプルな構文で、Pythonらしい直感的な書き方といえるでしょう。
日本語文字列を1文字ずつ処理する
# 日本語文字列を1文字ずつ処理
text = "アボカド"
for char in text:
print(f"文字:{char}")
# 出力結果:文字:ア
# 出力結果:文字:ボ
# 出力結果:文字:カ
# 出力結果:文字:ド
Pythonは日本語などのマルチバイト文字も1文字として正しく扱えます。バイト数を意識せずに文字単位でループ処理できるのはPython 3の大きなメリットです。
条件を付けて特定の文字だけ処理する
# 特定の文字だけを処理する
text = "dragon_fruit_and_avocado"
vowels = []
for char in text:
if char in "aeiou":
vowels.append(char)
print(f"母音一覧:{vowels}")
print(f"母音の数:{len(vowels)}")
# 出力結果:母音一覧:['a', 'o', 'u', 'i', 'a', 'a', 'o', 'a', 'o']
# 出力結果:母音の数:9
forループの中にif文を組み合わせることで、条件に合う文字だけを抽出できます。母音の抽出・特定文字のカウント・文字の分類など幅広い処理に応用できます。
enumerate()で位置情報と一緒に処理する方法
続いては、enumerate()を使って文字の位置(インデックス)と内容を同時に取得する方法を確認していきます。
enumerate()を使うと文字の位置番号と文字の内容を同時に取り出せます。特定の位置にある文字を調べたり、位置に応じた処理をしたりする場面で非常に役立ちます。
enumerate()の基本的な使い方
# enumerate()で位置と文字を同時に取得
text = "keyboard"
for i, char in enumerate(text):
print(f"位置{i}:{char}")
# 出力結果:位置0:k
# 出力結果:位置1:e
# 出力結果:位置2:y
# 出力結果:位置3:b
# 出力結果:位置4:o
# 出力結果:位置5:a
# 出力結果:位置6:r
# 出力結果:位置7:d
enumerate()はインデックスと要素のタプルを返します。start=1を指定すると1始まりの番号にもできます。文字の位置に応じた処理が必要な場面でとても便利です。
特定の文字の位置をすべて取得する
# 特定の文字が出現する位置をすべて取得
text = "dragon_fruit_and_avocado"
target = "a"
positions = []
for i, char in enumerate(text):
if char == target:
positions.append(i)
print(f"「{target}」の出現位置:{positions}")
print(f"出現回数:{len(positions)}回")
# 出力結果:「a」の出現位置:[1, 17, 19, 22]
# 出力結果:出現回数:4回
enumerate()とif文を組み合わせることで、特定の文字が何番目に出現するかをすべてリストとして収集できます。文字列検索やパターン解析で役立つパターンです。
偶数・奇数位置の文字を分けて処理する
# 位置の偶数・奇数で処理を分ける
text = "avocado"
even_chars = []
odd_chars = []
for i, char in enumerate(text):
if i % 2 == 0:
even_chars.append(char)
else:
odd_chars.append(char)
print(f"偶数位置:{''.join(even_chars)}")
print(f"奇数位置:{''.join(odd_chars)}")
# 出力結果:偶数位置:aoad
# 出力結果:奇数位置:vco
インデックスの偶数・奇数で分岐する処理は、簡易的な暗号化やデータのインターリーブ処理などに応用できます。
リスト内包表記で1文字ずつ処理する方法
続いては、リスト内包表記を使って文字列を1文字ずつ処理する方法を確認していきます。
forループでできる処理の多くは、リスト内包表記を使うことでより短くシンプルなコードで書き直せます。Pythonicな書き方として広く使われているパターンです。
文字列をリストに分割する
# 文字列を1文字ずつのリストに変換
text = "salmon"
# list()を使う方法
char_list1 = list(text)
# リスト内包表記を使う方法
char_list2 = [char for char in text]
print(char_list1)
print(char_list2)
# 出力結果:['s', 'a', 'l', 'm', 'o', 'n']
# 出力結果:['s', 'a', 'l', 'm', 'o', 'n']
list()を使うのが最もシンプルですが、リスト内包表記では変換ロジックを追加しやすい利点があります。用途に応じて使い分けましょう。
条件付きフィルタリングをリスト内包表記で書く
# 数字と英字を分離する
text = "avocado500gと ドラゴンフルーツ200g"
# 数字だけ抽出
digits = [char for char in text if char.isdigit()]
# アルファベットだけ抽出
letters = [char for char in text if char.isalpha() and char.isascii()]
print(f"数字:{''.join(digits)}")
print(f"英字:{''.join(letters)}")
# 出力結果:数字:5002
# 出力結果:英字:avocadog
isdigit()・isalpha()・isascii()などの文字判定メソッドとリスト内包表記を組み合わせることで、文字の種類による分類がシンプルに書けます。
文字を変換してから結合する
# 文字を変換してから結合する
text = "gorilla keyboard"
# 母音を大文字に変換する
result = "".join(
char.upper() if char in "aeiou" else char
for char in text
)
print(result)
# 特定の文字を置換する
result2 = "".join(
"*" if char == "a" else char
for char in text
)
print(result2)
# 出力結果:gOrIllA kEybOArd
# 出力結果:gorillA keyboArd → gorill* keybo*rd
# 出力結果:gorill* keybo*rd
ジェネレータ式とjoin()を組み合わせることで、文字を変換しながら新しい文字列を生成できます。条件に応じた文字の置換処理をコンパクトに書けるパターンです。
文字列の1文字ずつ処理の応用パターン
続いては、文字列を1文字ずつ処理する実践的な応用パターンを確認していきます。
文字単位の処理は文字の出現頻度分析・パリンドローム判定・簡易暗号化など、様々な実用的な処理の基盤になります。
文字の出現頻度を集計する
from collections import Counter
# 文字の出現頻度を集計する
text = "dragon_fruit_avocado_gorilla"
# Counterを使った集計
freq = Counter(text)
# 出現頻度上位5位を表示
print("出現頻度トップ5:")
for char, count in freq.most_common(5):
bar = "■" * count
print(f"「{char}」:{count}回 {bar}")
# 出力結果:出現頻度トップ5:
# 出力結果:「a」:5回 ■■■■■
# 出力結果:「o」:3回 ■■■
# 出力結果:「r」:3回 ■■■
# 出力結果:「_」:3回 ■■■
# 出力結果:「g」:2回 ■■
collectionsモジュールのCounterは文字列を渡すだけで各文字の出現回数を集計してくれます。most_common()で頻度の高い順に取り出せるため、テキスト分析に非常に便利です。
文字列を逆順に1文字ずつ処理する
# 逆順に1文字ずつ処理する
text = "keyboard"
# reversed()を使う方法
print("reversed():")
for char in reversed(text):
print(char, end=" ")
print()
# スライスを使う方法
print("スライス:")
for char in text[::-1]:
print(char, end=" ")
print()
# 出力結果:reversed():d r a o b y e k
# 出力結果:スライス:d r a o b y e k
reversed()やスライスの[::-1]と組み合わせることで、末尾から先頭に向かって1文字ずつ処理できます。
2つの文字列を1文字ずつ比較する
# 2つの文字列を1文字ずつ比較する
text1 = "avocado"
text2 = "avokado"
differences = []
for i, (c1, c2) in enumerate(zip(text1, text2)):
if c1 != c2:
differences.append((i, c1, c2))
if differences:
print("異なる位置:")
for pos, c1, c2 in differences:
print(f" 位置{pos}:「{c1}」→「{c2}」")
else:
print("2つの文字列は同じです。")
# 出力結果:異なる位置:
# 出力結果: 位置3:「c」→「k」
zip()で2つの文字列を同時にイテレートし、enumerate()で位置も取得することで、2つの文字列の差分を1文字単位で検出できます。スペルチェックや文字列の差分検出に応用できるパターンです。
文字列をN文字ずつまとめて処理する
# 文字列をN文字ずつまとめて処理する
text = "dragon_fruit"
n = 3
chunks = [text[i:i+n] for i in range(0, len(text), n)]
print(f"3文字ずつ分割:{chunks}")
# N文字ずつ区切って処理
for chunk in chunks:
print(f"チャンク:{chunk}({len(chunk)}文字)")
# 出力結果:3文字ずつ分割:['dra', 'gon', '_fr', 'uit']
# 出力結果:チャンク:dra(3文字)
# 出力結果:チャンク:gon(3文字)
# 出力結果:チャンク:_fr(3文字)
# 出力結果:チャンク:uit(3文字)
range(0, len(text), n)のstepをnにすることで、n文字ずつスライスして処理するパターンが実現できます。固定長フォーマットのデータ処理や暗号化処理などで活用できます。
まとめ
この記事では、Pythonで文字列を1文字ずつ処理する方法について、forループの基本・enumerate()との組み合わせ・リスト内包表記・応用パターンまで幅広く解説しました。
Pythonの文字列はイテラブルなため、forループに直接渡すだけで1文字ずつ取り出せます。enumerate()を使うと位置情報と文字を同時に取得でき、リスト内包表記を使うとより簡潔なコードで同じ処理が書けます。zip()と組み合わせた2文字列の比較や、Counterを使った頻度分析など、1文字ずつ処理する基本を押さえると様々な応用が広がります。
今回紹介したパターンを参考に、実際のコードで積極的に活用してみてください。