更新日:
【Ruby】 splitメソッドの使い方-基礎から応用を理解しよう
splitメソッドとは、文字列を指定した区切り文字で分割し、配列で返すメソッドです。splitメソッドの第一引数に区切り文字を指定し、第二引数に分割数を指定する事が出来ます。
splitメソッドを使えば、以下のコードのように文字列をカンマ(,
)で分割し、その分割した文字列を要素とした配列で取得する事が出来ます。
1
2
irb(main):001:0> "Apple,Orange,Cherry,Banana".split(',')
=> ["Apple", "Orange", "Cherry", "Banana"]
splitメソッドに指定する事が出来る区切り文字には、split(','
)のように文字列だけではなく正規表現もあります。
splitメソッドは、文字列を指定した区切り文字で分割して配列にしたい場合にとても便利なメソッドなので、是非マスターしていきましょう。
splitメソッドの基本的な使い方
この章では、豊富なサンプルコードを用いて以下を詳しく解説します。
- 基本構文
- 指定できる区切り文字の種類
- 分割する回数を制限する方法
基本構文
以下のコードのように、splitメソッドの「第一引数には区切り文字」を指定し、「第二引数には分割数」を指定します。
1
2
# split([sep[, limit]])
"文字列".split(区切り文字, 分割数)
例えば、以下のコードのようにsplitメソッドに区切り文字(':'
)だけ指定すると、文字列を区切り文字(':'
)で全て分割して配列で返します。
1
2
irb(main):001:0> "Tokyo:Saitama:Okinawa".split(':')
=> ["Tokyo", "Saitama", "Okinawa"] # 配列の要素は3つある
しかし、splitメソッドの第二引数に分割数(2
)を指定すると、以下のコードのように指定された数の分割しか行いません。
1
2
irb(main):002:0> "Tokyo:Saitama:Okinawa".split(':', 2)
=> ["Tokyo", "Saitama:Okinawa"] # 2分割に制限され要素は2つになる
文字列の後半のSaitama:Okinawa
にもコロンはありますが、文字列の左側からコロンを探すのでTokyo:Saitama
のコロンで2分割されます。
1
2
irb(main):003:0> ["Tokyo", "Saitama:Okinawa"].split(',')
NoMethodError (undefined method `split' for ["Tokyo", "Saitama:Okinawa"]:Array)
また、splitメソッドはStringクラスのメソッドなので、上記のコードのようにString以外に使用するとエラーになるので注意してください。
区切り文字の種類
splitメソッドの第一引数に指定する事が出来る区切り文字には、文字列以外にもnil、1バイトの空白文字、正規表現があります。
splitメソッドにこの区切り文字を指定すると、どんな分割が可能になるのかそれぞれの特徴を掴んでいきましょう。
文字列
区切り文字に文字列を指定すると、その文字列に一致する部分で分割されます。
1
2
3
4
5
irb(main):001:0>"Apple&Orange&Cherry&Banana".split('&')
=> ["Apple", "Orange", "Cherry", "Banana"]
irb(main):002:0> "AppleAndOrangeAndCherryAndBanana".split('And')
=> ["Apple", "Orange", "Cherry", "Banana"]
正規表現を使う
splitメソッドの区切り文字には、正規表現を指定する事が出来ます。文字列は、正規表現に一致する部分で分割されます。
1
"文字列".split(/正規表現/)
以下のコードのように文字列をカンマ(,
)に一致する部分で分割したい場合は、区切り文字を文字列にしたsplit(',')
でも実現出来ますね。
1
2
irb(main):001:0> "10:30,15:10".split(',')
=> ["10:30", "15:10"]
ただ"10:30,15:10"
をカンマだけではなく、カンマ(,) コロン(:)、それぞれの区切り文字で文字列を分割したい場合には、以下のコードのように区切り文字に正規表現を指定する事で実現する事が出来ます
1
2
irb(main):002:0> "10:30,15:10".split(/[:|,]/)
=> ["10", "30", "15", "10"]
このように区切り文字に正規表現を使うことで、柔軟に文字列を分割する事が出来ます。
1バイトの空白文字
1バイトの空白文字とは、以下のコードのようにsplitメソッドの区切り文字に、文字列の半角スペース' '
を指定します。
1
"文字列".split(' ')
このようにすると、以下のコードのように「その文字列の先頭と末尾の空白文字」を除いてくれ、その上で「空白文字に一致する部分」で分割します。
1
2
irb(main):001:0> " abc def g ".split(' ')
=> ["abc", "def", "g"]
上記の文字列の空白文字は半角スペースにしていますが、この文字列の「先頭と末尾を除外する空白文字」や「分割する対象の空白文字」は、以下のコードのように半角のスペースだけではなく、改行(\n
)、タブ(\t
)も対象となります。
1
2
3
4
5
irb(main):002:0> "\nabc\ndef\ng\n".split(' ')
=> ["abc", "def", "g"]
irb(main):003:0> "\tabc\tdef\tg\t".split(' ')
=> ["abc", "def", "g"]
このようにsplit(' ')
の区切り文字を指定すると、文字列に含まれる半角スペース、改行、タブを空白文字として、その文字列の先頭と末尾の空白文字の除外と空白文字に一致する部分で分割されます。
また、注意点として全角スペース
は空白文字の対象外です。
1
2
irb(main):004:0> " abc def g ".split(' ')
=> [" abc def g "]
上記のコードのように全角スペースが含まれた文字列にsplit(' ')
を実行しても、前後の全角スペースが除外されたり、全角スペースに一致する部分で分割されることはないので注意してください。
nil
区切り文字にnil
を指定した場合は、以下のように記述します。
1
"文字列".split(nil)
区切り文字にnilを指定すると、以下のコードのように「その文字列の先頭と末尾の空白文字」を除いてくれ、その上で「空白文字に一致する部分」で分割します。
1
2
irb(main):001:0> " abc def g ".split(nil)
=> ["abc", "def", "g"]
これは、先ほど解説したsplit(' ')
の1バイトの空白文字を指定した場合と同じです。また、文字列の「先頭と末尾を除外する空白文字」や「分割する対象の空白文字」も同様に半角スペース、改行、タブが対象となります。
1
2
3
4
5
irb(main):002:0> "\nabc\ndef\ng\n".split(nil)
=> ["abc", "def", "g"]
irb(main):003:0> "\tabc\tdef\tg\t".split(nil)
=> ["abc", "def", "g"]
更には、以下のコードのようにsplitメソッドの引数を省略した場合もsplit(nil)
やsplit(' ')
と同じ結果になります。
1
2
3
4
5
6
7
8
irb(main):004:0> " abc def g ".split(nil)
=> ["abc", "def", "g"]
irb(main):005:0> " abc def g ".split(' ')
=> ["abc", "def", "g"] # split(nil)と同じ
irb(main):006:0> " abc def g ".split
=> ["abc", "def", "g"] # split(nil)と同じ
つまり、上記のコードの3つとも「その文字列の先頭と末尾の空白文字」を除いてくれ、その上で「空白文字に一致する部分」で分割します。
そして、空白文字
とは半角スペース
、改行
、タブ
が対象となります。
分割数の制限
splitメソッドの第二引数に分割数を指定する事で、区切り文字に一致する部分の分割数を制限する事が出来ます。
1
2
# split([sep[, limit]])
"文字列".split(区切り文字, 分割数)
例えば、以下のコードのように第二引数に2を指定すると、指定した区切り文字(','
)に一致する最初の部分で2分割します。
1
2
irb(main):001:0> "abc,def,g,hi".split(',', 2)
=> ["abc", "def,g,hi"] # 2分割になる
3分割に制限する場合は、以下の通りになります。
1
2
irb(main):002:0> "abc,def,g,hi".split(',', 3)
=> ["abc", "def", "g,hi"] # 3分割になる
分割数に0を指定した場合
分割数に0を指定した場合は、分割数の制限なく区切り文字に一致する全ての部分で分割します。
1
2
irb(main):001:0> "abc,def,g,hi".split(',', 0)
=> ["abc", "def", "g", "hi"] # カンマに一致する全ての部分で分割する
そして、以下のコードのように分割数の制限がなく0に指定する場合は、第二引数を指定せずに省略が出来ます。
1
2
3
# "abc,def,g,hi".split(',', 0)と同じ
irb(main):002:0> "abc,def,g,hi".split(',')
=> ["abc", "def", "g", "hi"] # カンマsplitメソッドの返り値は、区切り文字で一致した部分を分割した配列です。に一致する全ての部分で分割する
また、",,,abc,def,g,hi"
の文字列に対してsplit(',')
を実行すると、以下のコードのように配列の要素が空になる場合でも分割されます。
1
2
irb(main):003:0> ",,,abc,def,g,hi".split(',')
=> ["", "", "", "abc", "def", "g", "hi"]
しかし、"abc,def,g,hi,,,"
の文字列に対してsplit(',')
を実行すると、["abc", "def", "g", "hi", "", "", ""]
とはならず、以下のコードのように末尾の場合だけ空の配列要素は作成されません。
1
2
3
irb(main):004:0> "abc,def,g,hi,,,".split(',')
=> ["abc", "def", "g", "hi"]
# ["abc", "def", "g", "hi", "", "", ""] にはならない
上記のコードのように配列末尾の空文字列は除外されます。
分割数の制限が必要な場合
無駄に分割する必要がない場合には、第二引数に分割数を指定し制限します。
例えば、以下のコードはカンマに一致する全ての部分で分割されますが(["abc", "def", "g"]
)、その後のfirstメソッドで分割された最初の"abc"
の要素だけ取得しています。
1
2
irb(main):001:0> first = "abc,def,g".split(',').first
=> "abc" # 分割した最初の要素しか使わない
分割された最初の要素だけ必要なので、他の箇所すべてを分割していく必要はないですよね。このように無駄に分割する必要がない場合には、以下のコードのように分割数を指定して制限してあげます。
1
2
3
irb(main):002:0> first = "abc,def,g".split(',', 2).first
=> "abc"
# "abc,def,gi".split(',', 2)は ["abc", "def,g"] の2分割に制限される
区切り文字に一致する部分すべてを分割していく必要がない場面では、分割数の制限をして無駄な処理を行わないようにしましょう。
splitメソッドの応用的な使い方
この章では、文字列を分割する際に良く使われるsplitメソッドとmapメソッドの応用的な使い方を解説します。また、splitメソッドを使う際の注意点も確認していきます。
mapメソッドと組み合わせる
splitメソッドの返り値は、文字列に対して指定した区切り文字で分割した配列です。この配列に対してmapメソッドを使えば、各要素を簡単に加工する事が出来ます。
1
"文字列".split(区切り文字, 分割数).map { |変数| 実行する処理 }
mapメソッドは、配列の要素の数だけブロック内で実行される処理を繰り返して新しい配列を返すメソッドです。mapメソッドの詳細は「mapメソッドの使い方」を参考にしてください。
分割した配列の要素を文字列から数値に変換
カンマ区切りの数字の文字列を数値に変換した配列が欲しい!と言う場合に、mapメソッドと組み合わせる事で簡単に実現出来ます。
例えば、以下のコードのようにカンマ区切りの数字の文字列にsplit(',')
を実行すると、カンマに一致する部分で分割されて配列になりますが、各配列の要素は文字列です。
1
2
3
4
5
6
irb(main):002:0> num_array = "1,2,55,6,9,3".split(',')
=> ["1", "2", "55", "6", "9", "3"]
irb(main):003:0> num_array[0]
=> "1" # 配列の最初の要素
irb(main):004:0> num_array[0].class
=> String # 要素が文字列だと分かる
ここでは文字列ではなく、数値に変換された要素が欲しいですよね。
mapメソッドを組み合わせると、以下のコードのように各要素が数値に変換された配列を取得する事が出来ます。
1
2
3
4
5
6
irb(main):005:0> num_array = "1,2,55,6,9,3".split(',').map{|n| n.to_i}
=> [1, 2, 55, 6, 9, 3]
irb(main):006:0> num_array[0]
=> 1 # 配列の最初の要素
irb(main):007:0> num_array[0].class
=> Integer # 要素が数値だと分かる
上記のコードは「split(',')
で分割された文字列の各要素」をmapメソッドのブロック変数n
に渡し、to_iメソッドで数値に変換しています。要素の数だけ繰り返し処理が実行されて、各要素を数値に変換した新たな配列を返します。
また、以下のコードのように条件が揃えば&:メソッド名
のように省略して記述することが出来ます。(詳細はmapメソッドの省略した書き方へ)
1
2
3
4
5
6
irb(main):008:0> "1,2,55,6,9,3".split(',').map{|n| n.to_i}
=> [1, 2, 55, 6, 9, 3]
# 省略した書き方
irb(main):009:0> "1,2,55,6,9,3".split(',').map(&:to_i)
=> [1, 2, 55, 6, 9, 3]
今回は、to_iメソッドで各要素の文字列を数値に変換する方法を解説しましたが、用途に合わせた要素の加工を試してみてください。
注意点
splitメソッドを使用する際に、文字列を変換するために無理やり使っていないか、目的にあったメソッドを使用できているかという点に注意してください。
splitメソッドの返り値は、配列です。「文字列を区切り文字に一致する部分で分割し、配列として取得したい場合」に使用されるメソッドですね。
1
2
irb(main):001:0> "abc,def,g".split(',')
=> ["abc", "def", "g"] # 返り値は配列
しかし、以下のコードのように「文字列の区切り文字をカンマ,
からコロン:
に置き換える目的」で「文字列→配列→文字列」と変換している場合は注意が必要です。
1
2
irb(main):002:0> "abc,def,g".split(',').join(':')
=> "abc:def:g"
上記のコードは、最終的に文字列にしているので、わざわざ配列を経由する必要がありません。文字列を置き換えるのが目的の場合は、以下のコードのようにsplitメソッドではなくgsubメソッドを使うべきです。
1
2
irb(main):003:0> "abc,def,g".gsub(',', ':')
=> "abc:def:g"
splitメソッドは、特定の区切り文字で文字列を分割する事が出来る便利なメソッドですが、返り値は配列です。その配列を使用して別の処理を行うことは良くありますが、今回のような文字列の置換が目的の場合は、splitメソッドを無理やり使うのではなく、目的に合った他のメソッドがないか考えるようにしましょう。
この記事のまとめ
- splitメソッドは、文字列を指定した区切り文字で分割し、配列で返すメソッド
- 第一引数に区切り文字を指定し、第二引数に分割数を指定する事が出来る
- 区切り文字は、文字列以外にもnil、1バイトの空白文字、正規表現を指定出来る