文字列を数値(Int, UInt32)としてmap処理する
あまりありませんが、文字列を数値として処理したい場合があります。
例えば。ABC...を受け取って、それらをBCD...と1つずつ文字をずらしたい場合などでです。
ここでは、文字列を数値へと変換し、そしてまた文字列に戻すプログラムを関数型プログラミングのスタイルで書いてみたいと思います。
サンプルコード
ここでは以下の仕様でサンプルプログラムを書いてみます。少し不思議な仕様ですが。。。笑
※Swiftでは"A"..."Y"
といったパターンマッチが使えよというサンプルにしたかった。
- A~Yの文字の場合、右に1つシフトする。(例:Bの場合、Cになる。)
- b~zの文字の場合、左に1つシフトする。(例:bの場合、aになる。)
- Z、a、その他の文字の場合はそのまま出力する。
上記仕様のshift()
関数を作成してみます。
func shift(_ str: String) -> String { return text.unicodeScalars .map { (scalar) -> UInt32 in switch scalar { case "A"..."Y": return scalar.value + 1 case "b"..."z": return scalar.value - 1 default: return scalar.value } } .compactMap(UnicodeScalar.init) .map(Character.init) .map(String.init) .joined() } let text = "bcdDEF" let result = shift(text) print(result) // abcEFG
文字列(String)から数値(UInt32)へ
unicodeScalars
プロパティにより、String.UnicodeScalarView
構造体を取得することができます。
こちらは、Unicode.Scalar
構造体のコレクションとなっており、イテレートすることができます。
Unicode.Scalar
構造体から、実際の値(UInt32
構造体)を取得するには、value
プロパティにアクセスします。
次のように書くことができます。
let scalars = "漢字も😊OK!".unicodeScalars.map{s -> UInt32 in s.value} print(scalars) // [28450, 23383, 12418, 128522, 79, 75, 33]
数値(UInt32)から文字列(String)へ
ここでは関数型プログラミングのスタイルで、4ステップを経て文字列へと変換しています。
let scalars: [UInt32] = [28450, 23383, 12418, 128522, 79, 75, 33] let str = scalars.compactMap(UnicodeScalar.init) .map(Character.init) .map(String.init) .joined() print(str) // 漢字も😊OK!
UnicodeScalar.init
でUInt32からUnicode.Scalarに変換する。UnicodeScalar.init
でCharacterに変換する。String.init
でStringに変換する。.joined()
でそれぞれの文字列を結合する。
UInt32からUnicodeScalarへの変換はcompactMap()
で行っています。
これは、UnicodeScalar.initで変換できなかった(nilになった)要素を排除するためです。
Character
構造体はString内の1文字を表す構造体です。
joined()
を利用して簡潔に書くため、一度各CharacterをStringに変換しています。
まとめ
StringからUInt32への変換は次のように行う。
String→String.UnicodeScalarView→UnicodeScalar→UInt32
UInt32からStringへの変換は次のように行う。 [UInt32]→[UnicodeScalar]→[String]→joined()→String
参考リンク
developer.apple.com developer.apple.com