Rubyで文字列処理を実装するときに悩みがちなのが、文字列の分割処理をどのように実装すればよいのかではないでしょうか。しかし、Rubyではsplit()と呼ばれるメソッドを一度呼び出すだけで、簡単に文字列を分割できます。
今回は、文字列の分割処理を実装する際に覚えるべきメソッド、split()メソッドの使用方法を、サンプルコードを交えて詳しく解説します。
引数の意味などを理解できれば、より複雑な文字列分割処理も実装できるようになるので、ぜひ参考にしてください。
なお、Rubyの魅力や特徴については以下の記事で詳しく解説していますので、こちらもぜひご覧くださいね。
みなさんこんにちは! 今回の記事は、 悩みを抱えた人 ・Rubyってどんなプログラミング言語なの?・Rubyを勉強すると将来役に立つかな?・Rubyのおすすめの学習方法が知りたい! というお悩みを解決する記事にな[…]
フリーランス案件を探すならこのエージェント!
転職を考えているならこのエージェント!
split()メソッドの基礎知識
Rubyで文字列を分割する処理を実装するためには、split()メソッドを呼び出せば良いことは、冒頭でも述べたとおりです。
split()メソッドは、Stringクラスのメソッドで2つの引数を持ちます。第一引数には、区切り文字を示す文字列を、第二引数には、分割する個数を数値で指定します。なお、いずれも省略可能です。戻り値は配列で、分割処理実施後の文字列が要素ごとに格納されています。
split()メソッドの使用方法
ここからは、実際にsplit()メソッドの使用方法について、サンプルコードを示しながら解説していきます。
引数で区切り文字を設定しよう
まずは、区切り文字が文字列中に存在する場合について、split()メソッドによってどのように文字列分割処理を表現すればよいのか、説明しましょう。
カンマやスラッシュなどで列挙された文字列を分割する際は、カンマやスラッシュなどの区切り文字をsplit()メソッドの第一引数に設定することで、綺麗に文字列を分割できます。以下のサンプルコードをご覧ください。
# 分割前の文字列
address = "181-0013/東京都/三鷹市/下連雀/3丁目/46-1"
# 「/」を境にして文字列分割
address_split = address.split("/")
# 要素ごとに変数の中身を表示
for item in address_split do
p item
end
変数addressには、スラッシュで区切られた住所情報が格納されています。この状態から、スラッシュごとに文字列を分割する処理を、split()メソッドを呼び出すことで実現しています(5行目)。
今回は、スラッシュごとに区切りたいため、split()メソッドの第一引数には「/」を渡します。文字列分割が成功した場合、配列が返されるので、for文などの繰り返し処理などで要素ごとに取り出すなどして活用できます。
なお、対象の文字列内に区切り文字が存在しなかった場合、文字列の分割処理は行われずに対象の文字列がそのまま配列の要素に設定されることに注意してください。
区切り文字を省略しても分割可能
次に、split()メソッドに引数を渡さないとどのような挙動になるのかについて解説していきます。以下のサンプルコードをご覧ください。
# 各単語ごとに半角スペースで区切られている
product_str = "りんご 豚肉 インスタントラーメン 牛乳"
product_list = product_str.split()
p product_list # ["りんご", "豚肉", "インスタントラーメン", "牛乳"]
# キャベツとにんじんの間は、半角スペース2つ
# にんじんとたまねぎの間は、全角スペース1つ
product_str = "キャベツ にんじん たまねぎ"
product_list = product_str.split()
p product_list # ["キャベツ", "にんじん たまねぎ"]
実行結果を見ての通り、半角スペースごとに単語が区切られながら配列に格納されていることが分かります。split()メソッドに引数を渡さない場合は、半角スペースごとに文字列を分割するのがデフォルトの動作です。
また、10行目にあるように半角スペースが2つ以上含まれている場合は除去した上で配列に格納されます。一方、全角スペースが含まれている場合は分割処理は適用されないので、実装時には十分注意しましょう。
半角スペース以外にも、以下のサンプルコードのように、改行(\n)やタブ入力(\t)が含まれている場合も、文字列分割されます。
data_nl = "1234\n42\n6345\n43325\n436"
data_tb = "1234\t42\t6345\t43325\t436"
data_nl_array = data_nl.split()
data_tb_array = data_tb.split()
p data_nl_array # ["1234", "42", "6345", "43325", "436"]
p data_tb_array # ["1234", "42", "6345", "43325", "436"]
分割数を制限する
split()メソッドを使った文字列の分割処理では、分割する数を引数で決定できます。
対象の文字列に対して冒頭の部分のみ抜き出したい場合などに便利です。分割数は、split()メソッドの第二引数に対して整数値を渡すことで決めることができます。サンプルコードは、以下の通りです。
address = "260-0026/千葉県/千葉市/中央区/千葉港/1−1"
# 最大で2つ分割
address_no = address.split("/", 2);
p address_no # ["260-0026", "千葉県/千葉市/中央区/千葉港/1−1"]
スラッシュで区切られた住所情報のうち、今回は冒頭の郵便番号のみを抜き出したいので、split()メソッドの第二引数に最大分割数の2を指定します。最大分割数を指定することで、分割処理が途中で切り上げられるので、冒頭の郵便番号だけが分割された状態で配列が生成されます。
なお、分割数を0または負の整数にした場合は、分割数を省略した場合と同様の動作となります。つまり、分割の制限なしに文字列の分割処理が行われるということです。以下のサンプルコードで、動作を確認してください。
name_str = "鈴木花子,佐藤太郎,伊藤翔平,山本裕典"
# 最大で2つ分割
name_list_1 = name_str.split(",", 2); # 分割数 2
name_list_2 = name_str.split(",", 0); # 分割数 0:分割制限なし
name_list_3 = name_str.split(",", -1); # 分割数-2:分割制限なし
p name_list_1.size # 2
p name_list_2.size # 4
p name_list_3.size # 4
split()メソッドを使った応用テクニック
split()メソッドの基本的な使用方法が理解できたら、次はsplit()メソッドを上手に使いこなすための応用的なテクニックを紹介しましょう。
正規表現を使った文字列分割
応用テクニックの1つ目は、正規表現を利用した文字列分割処理の実装です。正規表現とは、対象の文字列内に指定した文字が含まれるか否かを評価するために記述する、記号などを複数組み合わせた特殊な文字列です。
例として、日時と時刻を示す文字列「2021/07/06 12:43:23」を、各々分割したいとしましょう。今まで通りの発想に基づけば、スラッシュとコロンと半角スペースが区切り文字になります。
しかし、split()メソッドには一回の分割処理に1つの区切り文字しか引数として渡せません。つまり、今回の例においては最低でも3回呼び出さなければならないのです。
しかし、正規表現を利用することで、split()メソッド一回の呼び出して、複数の区切り文字に基づいた文字列分割処理を実行できるようになります。サンプルコードは、以下の通りです。
date_time_str = "2021/07/06 12:43:23"
# 正規表現の定義
pattern = /[\/ \:]/
# 正規表現による文字列分割処理の実行
date_time_array = date_time_str.split(pattern)
p date_time_array # ["2021", "07", "06", "12", "43", "23"]
サンプルコードの4行目において、正規表現を使った文字列パターンを定義しています。正規表現では、スラッシュで囲まれた中に検索する文字や検索条件などを記号を使って記述します。
例えば「/apple/」は、検索対象の文字列中に「apple」が含まれているかを意味する正規表現となります。これが正規表現の最も基本的な仕組みです。
また、角括弧で囲んだ場合は、角括弧で囲まれた文字が1つでも含まれているかを意味するようになります。例えば「/[xyz]/」は、検索対象の文字列内に「x」「y」「z」のいずれかが含まれているかを表します。
上で挙げた例の中で記述した角括弧やスラッシュは、正規表現を記述するうえで特別な意味を持つ文字と解釈され「メタ文字列」と呼ばれます。もし、メタ文字列である角括弧やスラッシュが、検索対象の文字列に含まれているかを示したい場合は、バックスラッシュを使って「\/」「\[」「\]」のように記述しましょう。
さて、今回は対象の文字列内にスラッシュ・半角スペース・コロンが含まれているかを評価したいため、正規表現は「/[\/ \:]/」と定義します。そして、split()メソッドに正規表現を格納した変数を引数として与えることで、複数の区切り文字に対応した分割処理が実行されます。
文字列を1文字ごとに分割
2つ目は、文字列をバラバラにする方法です。区切り文字に関わらず、1文字ずつ分割したい場合は、split()メソッドの引数に空文字列を指定します。サンプルコードは、以下の通りです。
alphabet_str = "abcdefg"
# 空文字列「''」を指定
alphabet_array = alphabet_str.split('')
p alphabet_array # ["a", "b", "c", "d", "e", "f", "g"]
map()メソッドと組み合わせる
3つ目は、map()メソッドとの組み合わせ処理です。map()メソッドは、配列の各要素に対して何らかの処理を行いたい場合に呼び出すメソッドです。split()メソッドの戻り値が配列であることから、map()メソッドと併用することで、さらに複雑な文字列処理を実装できます。
例として「氏名:性別に対応する数字」がカンマ区切りで列挙された文字列から「氏名(性別)」形式の文字列を生成したいとします。
split()メソッドで氏名ごとに分割した後に、各氏名ごとに文字列整形の処理が必要になるため、その部分をmap()メソッドを使って実装していきます。サンプルコードは、以下の通りです。
# 「氏名:性別」で列挙された文字列から、「氏名(性別)」形式の文字列を生成するプログラム
# (1:男性、2:女性を意味する)
participant_str = "佐藤ハナコ:2,鈴木康平:1,田中工:1,渡辺舞:2,高橋亮平:1"
participant_list = participant_str.split(",").map do |item|
# 氏名と性別を分割
array = item.split(":")
str = array[0]
if array[1] == "1"
# 「氏名(男性)」の形式で文字列を生成
str = str + "(" + "男性" + ")"
elsif array[1] == "2"
# 「氏名(女性)」の形式で文字列を生成
str = str + "(" + "女性" + ")"
end
end
for item in participant_list do
p item # 佐藤ハナコ(女性) 鈴木康平(男性) ...
end
map()メソッドは、配列などを含むEnumerableクラスのメソッドです。したがって、5行目の「split(“,”).map」のように、メソッドチェーン形式で呼び出すことが可能です。doに続けて記述されている変数itemには、split()メソッドで分割した文字列が一つずつ代入され、後続の処理に活かされます。
map()メソッドでは、最後に実行された文の左辺(サンプルコードにおける変数str)が、配列の一要素として格納されます。つまり「佐藤ハナコ:2」に対して「佐藤ハナコ(女性)」が要素として格納されるということです。
最後に
さて、ここまでRubyで文字列を分割する方法(split()メソッド)について解説してきましたがいかがでしたか?
使い方自体はそれほど難しくなく、他のメソッドと組み合わせるとさらに複雑な分割処理も可能となります。
実際の開発でも頻繁に登場するメソッドになりますので、ぜひ今回の記事でしっかりとマスターしておいてくださいね。
このブログを通じて少しでも「傍(はた)を楽(らく)にする」ことができていれば嬉しく思います。
最後まで読んで頂きありがとうございました。