文字列を区切りで分割して要素を取り出し、逆に要素を区切りで結合して1つの文字列に戻す操作は、テキスト処理の基本です。
Pythonではsplit
とjoin
を使うことで、短く読みやすいコードで実現できます。
本記事ではsplitとjoinの要点と使い分けを、初心者の方にもわかりやすく解説します。
Pythonのsplitとjoinの基本
文字列を分割するsplitの概要
split
は文字列メソッドで、指定した区切りで文字列を分割し、リストにして返します。
区切りを指定しない場合は連続する空白類文字(スペース、タブ、改行)を1つの区切りとして扱い、空要素は捨てられます。
テキストを単語ごとやフィールドごとに取り出すときに使います。
文字列を結合するjoinの概要
join
は区切り文字側の文字列メソッドで、引数の繰り返し可能オブジェクト(iterable)に含まれる文字列要素を、区切りを挟んで結合します。
CSV風の出力や表示用のフォーマット作成に向いています。
- 関連記事:文字列の結合と繰り返し
構文と戻り値(list/str)
"text".split(sep=None, maxsplit=-1)
→ 戻り値はlist"text".rsplit(sep=None, maxsplit=-1)
→ 戻り値はlist(右から分割)"sep".join(iterable)
→ 戻り値はstr
join
に渡す要素はすべて文字列である必要があります。
数値が混ざる場合はstr
で事前に変換します。
- 関連記事:変数の使い方完全入門
splitの使い方(区切り・maxsplit・rsplit)
空白で分割する(split)
区切りを省略してsplit()
を呼ぶと、連続する空白類を1つの区切りとして扱い、先頭や末尾の空白も無視されます。
これは自然言語の単語分割や、空白区切りのログの処理で便利です。
# 空白類(スペース・タブ・改行)をまとめて区切りとして扱う
text = " Alice\tBob Charlie\nDavid "
words = text.split() # sepを省略
print(words) # 空要素は自動的に除去される
['Alice', 'Bob', 'Charlie', 'David']
空白省略のsplitは「空を捨てる」「連続空白を1つとみなす」のがポイントです。
区切り文字を指定して分割(カンマ/タブなど)
sep
を指定すると、その文字列に一致する箇所で分割します。
連続する区切りは空文字として結果に残ります。
# カンマ区切り
csv_like = "a,b,,d"
print(csv_like.split(",")) # 連続カンマは空文字要素を生む
# タブ区切り
tsv = "x\ty\t\tz"
print(tsv.split("\t"))
['a', 'b', '', 'd']
['x', 'y', '', 'z']
厳密な列数を保ちたいときはsepを明示、単語分割のように「空を捨てたい」ときはsep=None
のsplit()
を使い分けます。
- 関連記事:区切り文字自体を含めて3つに分割する
maxsplitで分割回数を制限
maxsplit
は分割実行回数の上限です。
余りは最後の要素に残ります。
record = "name:alice:developer:tokyo"
print(record.split(":", maxsplit=2)) # 左から2回だけ分割
print(record.rsplit(":", maxsplit=1)) # 右から1回だけ分割
['name', 'alice', 'developer:tokyo']
['name:alice:developer', 'tokyo']
左から区切るのか右から区切るのかで抽出しやすさが変わるため、次のrsplit
も覚えておくと便利です。
- 関連記事:スライスで文字列の一部を取得する
右から分割するrsplit
rsplit
は右側から分割を行います。
末尾の可変長部分を取りたいケースで有効です。
path = "home/user/projects/python/app.py"
head, tail = path.rsplit("/", maxsplit=1) # 右から1回分割
print(head)
print(tail)
home/user/projects/python
app.py
連続区切りで生じる空文字の扱い
sep
を指定したsplit
では、区切りが連続すると空文字が結果に含まれます。
一方、sep=None
のsplit()
は空白をまとめて扱うため空要素は発生しません。
用途に応じて後処理が異なります。
s1 = "a,,b,,c"
print(s1.split(",")) # 空文字を含む
print([x for x in s1.split(",") if x]) # 空要素を除去する例
s2 = "a b c"
print(s2.split()) # 連続空白でも空要素なし
['a', '', 'b', '', 'c']
['a', 'b', 'c']
['a', 'b', 'c']
空要素を保持したいか、無視したいかでsep指定の有無を選ぶのがコツです。
空文字の区切りはエラー(ValueError)
split
とrsplit
では、区切りに空文字(“”)は指定できません。
指定するとValueErrorになります。
try:
"abc".split("") # 空文字をsepに指定 → 例外
except Exception as e:
print(type(e).__name__, str(e))
ValueError empty separator
1文字ずつ分解したい場合はlist("abc")
や[*"abc"]
を使ってください。
joinの使い方(リストを文字列に結合)
区切り文字.join(iterable)の基本
join
は区切り文字の文字列に対して呼び出します。
引数は文字列の反復可能オブジェクトです。
words = ["red", "green", "blue"]
result = ", ".join(words) # カンマ+スペースで結合
print(result)
red, green, blue
joinは「区切り側.メソッド(要素群)」という呼び出し順に注意します。
- 関連記事:リスト(list)の使い方
改行やタブで結合する
ログや表形式の出力では、改行やタブを区切りにすると見やすくなります。
lines = ["line1", "line2", "line3"]
print("\n".join(lines)) # 改行で結合
cells = ["A", "B", "C"]
print("\t".join(cells)) # タブで結合
line1
line2
line3
A B C
数値を含む場合はstrで変換してからjoin
join
は要素がすべて文字列である必要があります。
数値が混ざるなら、map(str, iterable)
などで変換します。
items = ["id", 1001, 3.14, True]
safe = ", ".join(map(str, items)) # すべて文字列化してから結合
print(safe)
id, 1001, 3.14, True
リスト内包表記で[str(x) for x in items]
としても同様です。
- 関連記事:文字列と数値の型を変換したい
空リストや1要素の結合結果
- 空リストを結合すると空文字になります。
- 1要素だけなら区切りは挟まれずその要素自体が返ります。
print("|".join([])) # 空 → ""
print("|".join(["only"])) # 1要素 → 区切りなし
only
上の最初の行は空行(空文字)の出力です。
+連結よりjoinが速い理由(概要)
複数の文字列を+
で都度連結すると中間生成物が何度も作られるため非効率です。
join
は必要な長さを見積もって1回で連結するため、要素数が多いと特に高速でメモリ効率も良くなります。
多数結合はjoin、少数の結合や可読性重視の場面はf-stringという使い分けが実務的です。
よくある実用例とパターン
CSV風の文字列をsplitしてリスト化
単純なカンマ区切りであればsplit(",")
で扱えます。
実際のCSVは引用符やエスケープがあるためcsv
モジュールが安全ですが、簡易用途ならこれで十分です。
line = "Alice,24,Engineer,Tokyo"
fields = line.split(",")
print(fields)
['Alice', '24', 'Engineer', 'Tokyo']
厳密なCSVの読み書きはcsv.reader/csv.writerの利用を検討してください。
- 関連記事:CSVを読み込む・書き出す
キー=値の文字列を2つに分割(maxsplit=1)
設定行のようにkey=value
形式なら、最初の=
だけで分割すると右側に=を含んだ値が来ても安全です。
config = "path=/usr/local/bin=preferred"
key, value = config.split("=", maxsplit=1)
print(key)
print(value)
path
/ usr/local/bin=preferred
右側に=を含み得る場合はmaxsplit=1が定石です。
右端を基準にしたい場合はrsplit("=", 1)
を使います。
- 関連記事:辞書(dict)の基本的な使い方
リストを区切り付きでjoinして出力
ログや画面表示では、区切り付きで読みやすく整形します。
cols = ["time=12:00", "level=INFO", "msg=started"]
line = " | ".join(cols)
print(line)
time=12:00 | level=INFO | msg=started
見せ方を統一したいときは区切りを1カ所で定義し、全出力で共通化するとメンテナンス性が上がります。
入力行をsplitしてフィールドに分解
ユーザー入力やログ行を空白区切りで分解する例です。
連続空白をまとめて扱えるsplit()
が便利です。
line = "GET /index.html 200 123ms"
method, path, status, latency = line.split() # 空白をまとめて区切る
print(method, path, status, latency)
GET /index.html 200 123ms
フィールド数が想定より多い/少ない可能性がある場合は、maxsplit
やtry/except
で堅牢にすると安全です。
- 関連記事:try-exceptで例外処理を実装する
参考表: splitの挙動まとめ
呼び方 | 連続区切りの扱い | 先頭/末尾の区切り | 空要素の発生 |
---|---|---|---|
s.split() | 空白類を1つに圧縮 | 無視 | しない |
s.split(“,”) | 区切りごとに厳密一致 | そのまま | する |
s.rsplit(“,”, 1) | 右から分割 | そのまま | する |
「空白をまとめて処理したいならsepを省略、厳密に列を保ちたいならsepを指定」が判断基準です。
まとめ
splitは文字列をリストへ、joinはリストを文字列へという対応関係を理解すれば、文字列処理の多くは自然に書けるようになります。
空白をまとめるsplit()
と、厳密な列を保つsplit(sep)
を使い分け、必要に応じてmaxsplit
やrsplit
で欲しい部分だけを取り出しましょう。
結合はjoin
を基本とし、数値は文字列化してから渡すこと、そして多数要素の結合ではjoinが高速という原則を押さえておくと実務で役立ちます。