はじめに
Elixirで文字列を1文字ずつ分割して処理したい場合によく利用される関数として、
String.codepoints()とString.to_charlist()があります。
String.codepoints()は1文字ずつのListに変換されるのに対し、
String.to_charlist()は、(その名の通り)charlistに変換されます。
iex(1)> pattern = "012345"
"012345"
iex(2)> String.codepoints(pattern)
["0", "1", "2", "3", "4", "5"]
iex(3)> String.to_charlist(pattern)
'012345'
とりあえずここでは、それぞれ、変数a, 変数bに入れておきましょうか。
iex(4)> a = String.codepoints(pattern)
["0", "1", "2", "3", "4", "5"]
iex(5)> b = String.to_charlist(pattern)
'012345'
任意の位置の1文字を取り出す
次に、任意の位置の1文字を取り出す処理の例です。
- 1文字目
iex(6)> Enum.at(a, 0)
"0"
iex(7)> a |> hd
"0"
iex(8)> Enum.at(b, 0)
48
iex(9)> b |> hd
48
- 6文字目
iex(10)> Enum.at(a, 5)
"5"
iex(11)> Enum.at(b, 5)
53
codepoints()では文字列がそのまま1文字ずつの文字列に変換されるので、
他の関数で再利用したり、出力する場合に処理が楽なのですが、
to_charlist()だと、char型なので再度文字列型への変換が必要な場合が多いです。
<<>>記法
文字列に変換する場合は、<<>>で囲みます。
(よくこの記法を忘れるので、忘備録的な記事だったりします)
iex(12)> b |> hd
48
iex(13)> <<b |> hd>>
"0"
iex(14)> Enum.at(b, 5)
53
iex(15)> <<Enum.at(b, 5)>>
"5"
そのほか、<<>>記法の内部で値を列挙して、、
iex(16)> <<97, 98, 99, 100>>
"abcd"
でも、下記はエラーになります。
iex(17)> b
'012345'
iex(18)> <<b>>
** (ArgumentError) construction of binary failed: segment 1 of type 'integer': expected an integer but got: '012345'
(stdlib 4.2) eval_bits.erl:143: :eval_bits.eval_exp_field/6
iex:18: (file)
to_string()での変換
この場合、to_string()で文字列に変換できます。
iex(19)> b
'012345'
iex(20)> to_string(b)
"012345"
では、、charlistの任意の1文字をto_string()で変換するとどうなるか?
iex(21)> Enum.at(b, 0)
48
iex(22)> to_string(Enum.at(b, 0))
"48"
'0'の文字コード48が、文字列に変換されて出力されてしまいます。
このあたり、間違えやすいので、記憶違いに注意ですね。
?演算子
ちなみに、任意の文字の文字コードを取得したい場合は、?演算子 を使います。
(? が演算子なのか記法なのかは不明。とりあえずこの記事では ?演算子 と呼ぶことにします)
iex(23)> ?0
48
iex(24)> ?1
49
iex(25)> ?a
97
iex(26)> ?b
98
iex(27)> ?A
65
iex(28)> ?B
66
以上です。
他にも、思い出したら追記します。