色々な言語の文字列分割個数指定

「文字列を特定の区切り文字で分割し、配列相当のデータ構造で返す」という関数/メソッドは多くの言語が組込みで提供している。そして、その関数/メソッドの引数には区切り文字に加えて、オプションとして分割する個数を与えることができる。
この分割個数の指定の仕様が、言語によって微妙に異なっていたのでまとめてみた。

以下、全て"1:2:3:4:5"という文字列をコロンで分割する場合で考える。

Python の場合(str.split

第2引数を「分割処理を行う上限回数」として扱う。上限を超えた分は分割せず、最後の要素に残る。

print("1:2:3:4:5".split(":", 3))

上記コードだと34の間までを分割し、それ以降は分割しない。

$ python3 -V

$ python3 split.py
['1', '2', '3', '4:5']

JavaScript の場合(String.prototype.split

第2引数を「分割後の最大個数」として扱う。上限を超えた分は捨てられる。

console.log("1:2:3:4:5".split(":", 3))

上記コードだと23の間まで分割し、3の後ろのコロン以降は捨てられる。

$ node -v
v8.4.0

$ node split.js
[ '1', '2', '3' ]

Ruby の場合(String#split

第2引数を「分割後の最大個数」として扱う。上限を超えた分は分割せず、最後の要素に残る。

p "1:2:3:4:5".split(":", 3)

上記コードだと23の間まで分割し、それ以降は分割しない。

$ ruby -v
ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-darwin16]

$ ruby split.rb
["1", "2", "3:4:5"]

Java の場合(String.split

Ruby と同様。

import java.util.Arrays;

class Split {
    public static void main(String[] args) {
        System.out.println(Arrays.toString("1:2:3:4:5".split(":", 3)));
    }
}
$ java -version
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)

$ java Split
[1, 2, 3:4]

Go の場合(strings.SplitN

Ruby, Java と同様。(メソッドではなく関数)

package main

import (
    "fmt"
    "strings"
)

func main() {
    fmt.Printf("%q\n", strings.SplitN("1:2:3:4:5", ":", 3))
}
$ go version
go version go1.9 darwin/amd64

$ go run split.go
["1" "2" "3:4:5"]

PHP の場合(explode

Ruby, Java, Go と同様。(メソッドでなく関数)
Go のstrings.SplitNとは微妙に引数の取り方が異なる。紛らわしい。

<?php
print_r(explode(":", "1:2:3:4:5", 3));
$ php -v
PHP 7.1.8 (cli) (built: Aug  7 2017 15:02:45) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies

$ php split.php
Array
(
    [0] => 1
    [1] => 2
    [2] => 3:4:5
)

なお同じことをしそうな組み込み関数str_splitは全く仕様が異なる。紛らわしい。

まとめ

Python, JavaScript, Ruby で仕様が違うことに気づいたのでいざ色々と調べてみたら PythonJavaScript 以外はほぼ同じだった。

Python, JavaScript の分割仕様もだが、PHP もいざ使う時に嵌りそうなので注意したいところ……