CODE Polyglot / 入門 / 第14回

文字列を区切る — カンマで分けて、空の項目も数える

「東京,大阪,名古屋」のような文字列をカンマで区切って、項目の数と中身を出します。区切る関数(split)が、空の項目、とくに最後の空の項目をどう扱うかは、言語によって違います。

画面にこう出れば正解

どの言語で書いても、同じ入力なら画面に出る文字は1文字も違わない、というのが正解の決め方です(例は Python で動かしたときのコマンドです)。

基本

$ python3 split.py 東京,大阪,名古屋
3項目
1: 東京
2: 大阪
3: 名古屋

間が空

$ python3 split.py 東京,,名古屋
3項目
1: 東京
2: (空)
3: 名古屋

最後が空

$ python3 split.py 東京,大阪,
3項目
1: 東京
2: 大阪
3: (空)

最後に空が2つ

$ python3 split.py 東京,,,
4項目
1: 東京
2: (空)
3: (空)
4: (空)

先頭が空

$ python3 split.py ,東京
2項目
1: (空)
2: 東京

区切りなし

$ python3 split.py 東京
1項目
1: 東京

空

$ python3 split.py ""
項目がありません

空白は残す

$ python3 split.py "東京, 大阪"
2項目
1: 東京
2:  大阪

10言語のプログラム

どれもそのまま保存して動かせます。毎朝、上の正解の例をすべて実際に動かして確かめています。

split.php8.4.26 で 8 / 8 件の出力が正解と一致

<?php
// カンマで区切って、項目の数と中身を出す。空の項目も1つと数える
$s = $argv[1];
if ($s === '') {
    echo "項目がありません\n";
    exit;
}

// explode は、間・先頭・最後の空の項目も残す(空の文字列だけは [""] になるので、先に調べた)
$items = explode(',', $s);
echo count($items) . "項目\n";
foreach ($items as $i => $item) {
    if ($item === '') {
        $item = '(空)';
    }
    echo ($i + 1) . ": " . $item . "\n";
}

動かし方(ファイルを保存したフォルダで) ・ PHP を入れる

$ php split.php 東京,大阪,名古屋

言語でつまずきやすいところ

初心者がよく書く形(各言語で最初に習う書き方をそのまま使ったもの)を、同じ正解表で動かした結果です。言語を出した答えごとにまとめ、赤い字はその言語が実際に出した間違った行です。

入力初心者がよく書く形の答え(10言語)
基本東京,大阪,名古屋

✓10言語すべて正解

間が空東京,,名古屋
  • Swift2項目
    2: 名古屋
  • PHP・Python・Go・JavaScript・Java・C#・Rust・Ruby・Kotlin✓ 正解
最後が空東京,大阪,
  • Java・Ruby・Swift2項目
  • PHP・Python・Go・JavaScript・C#・Rust・Kotlin✓ 正解
最後に空が2つ東京,,,
  • Java・Ruby・Swift1項目
  • PHP・Python・Go・JavaScript・C#・Rust・Kotlin✓ 正解
先頭が空,東京
  • Swift1項目
    1: 東京
  • PHP・Python・Go・JavaScript・Java・C#・Rust・Ruby・Kotlin✓ 正解
区切りなし東京

✓10言語すべて正解

空""

✓10言語すべて正解

空白は残す"東京, 大阪"

✓10言語すべて正解

この回でやること

  • 文字列を、決まった文字(カンマ)で区切る
  • 区切った項目に、番号を付けて出す
  • 空の項目を見分ける

この回の決まり

  • カンマとカンマの間が何もなければ、空の項目として数える(「(空)」と出す)。先頭や最後のカンマの外側も、空の項目として数える
  • 入力が空の文字列なら「項目がありません」
  • 項目の前後の空白は取らない(「東京, 大阪」の2つ目は「 大阪」)

解説

split は便利だが、空の項目の扱いが違う

どの言語にも、文字列を区切る関数(split・explode・Split・components など)があります。「東京,大阪,名古屋」のように空の項目がなければ、どれも同じ3つに分けます。

違いが出るのは、「東京,,名古屋」のように空の項目があるときや、「東京,大阪,」のように最後がカンマで終わるときです。各言語のいちばん普通の書き方で試した結果です。

書き方空の項目「東京,,,」を区切ると
PHP explode・Python split(",")・Go strings.Split・JavaScript split(",")・C# Split(',')・Kotlin split(",")・Rust split(',')すべて残す4項目
Java split(",")・Ruby split(",")最後に続く空の項目だけ取り除く1項目
Swift split(separator: ",")すべて取り除く1項目

Java・Ruby は、最後の空の項目を残したいときに split(",", -1) と書きます。Swift は split(separator: ",", omittingEmptySubsequences: false) と書くか、components(separatedBy: ",") を使います。

なぜ大事か

CSV の1行や、フォームの「タグ(カンマ区切り)」の欄では、空の項目にも意味があることがあります。たとえば「名前,電話,メール」の電話が空の行で、空の項目が消えると、メールが2番目に繰り上がってしまいます。

練習

  1. 空の項目を取り除いて出すようにしてみましょう
  2. 項目の前後の空白を取り除いてから出すようにしてみましょう