「東京,大阪,」を split したら、Java・Ruby・Swift は最後の空の項目を捨てた ― その書き方、本当に通る?⑦

C#
B!

「東京,大阪,」をカンマで区切ると、項目はいくつでしょうか。最後のカンマの後ろに空の項目が1つあると数えれば、3項目です。各言語のいちばん普通の split で区切ると、10言語中3言語が2項目と答えました。

何をしたか

CODE Polyglot の入門 第14回 は、カンマ区切りの文字列を区切って、項目の数と中身を出すプログラムです。カンマとカンマの間が何もなければ空の項目として数え、「(空)」と出すのが正解です。先頭や最後のカンマの外側も、空の項目として数えます。

Java ならこう書きます。

String[] items = s.split(",");
System.out.println(items.length + "項目");

毎朝の検証と同じ Linux の環境で動かした結果です。

入力正解Java split(",")・Ruby split(",")Swift split(separator: ",")ほかの7言語
東京,大阪,名古屋3項目3項目3項目3項目
東京,,名古屋3項目3項目2項目3項目
東京,大阪,3項目2項目2項目3項目
東京,,,4項目1項目1項目4項目
,東京2項目2項目1項目2項目

「ほかの7言語」は、PHP explode・Python split(",")・Go strings.Split・JavaScript split(",")・C# Split(',')・Kotlin split(",")・Rust split(',') です。どれも空の項目をすべて残しました。

捨て方は2通り

  • Java・Ruby: 最後に続く空の項目だけを捨てる。途中と先頭の空の項目は残す。東京,,, は、最後の3つがすべて空なので、1項目になった
  • Swift: split(separator:) は、空の項目を場所に関係なくすべて捨てる

Java と Ruby は、空の項目が途中にあるときは正しく数えるので、テストの入力が 東京,,名古屋 だけだと気づけません。最後がカンマで終わる入力を試して、はじめて分かります。

なぜ困るか

CSV の1行や、フォームの「カンマ区切りで入力」の欄では、空の項目にも意味があります。たとえば「名前,電話,メール」の電話だけが空の行で空の項目が消えると、メールが2番目に繰り上がります(Swift の場合)。最後の項目が空の行では、Java・Ruby でも、上の 東京,大阪, と同じように項目の数が1つ減ります。

どう直したか

Java と Ruby は、2つ目の引数に -1 を渡すと、最後の空の項目も残します。

// split(",") は最後に続く空の項目を取り除くので、2つ目の引数に -1 を渡して残す
String[] items = s.split(",", -1);
# split(",") は最後の空の項目を捨てる。2つ目の引数に -1 を渡すと、最後の空の項目も残す
items = s.split(",", -1)

Swift は、omittingEmptySubsequences: false を付けます。

// split(separator:) は空の項目をすべて取り除くので、omittingEmptySubsequences: false で残す
let items = s.split(separator: ",", omittingEmptySubsequences: false)

直した版は、10言語とも8件中8件が正解になりました。

まとめ

  • 同じ split という名前でも、空の項目の扱いは言語によって違う。10言語中3言語が、最後の空の項目を捨てた
  • Java・Ruby は最後に続く空の項目だけ、Swift は空の項目をすべて捨てる。Java・Ruby は途中の空の項目では気づけない
  • 空の項目を残すなら、Java・Ruby は split(",", -1)、Swift は omittingEmptySubsequences: false
  • テストには「最後がカンマで終わる入力」を入れる
  • 10言語の全プログラムは 入門 第14回 にあります
B!
← 一覧へ戻る