![見出し画像](https://assets.st-note.com/production/uploads/images/129849664/rectangle_large_type_2_35c67f4ec323625d16ea11bcda37ac83.png?width=1200)
[SCSS|Sass] 文字列型の数字をちゃんと数値型にしたい(1)
引数などで受け取った数字が文字列型で、数値型に変換したいとき。
こんな風にマップを作る。
$num-map: (
'0': 0,
'1': 1,
'2': 2,
'3': 3,
'4': 4,
'5': 5,
'6': 6,
'7': 7,
'8': 8,
'9': 9,
);
SCSS のマップというのは、いわゆる連想配列のこと。
リストに『キー(key)』と『値(value)』を保存できる。
上記の例では $num-map というマップで、キーを文字列型の数字、値を数値型の数字にしている。
map-get($num-map, $str)
後は map-get 関数でマップから文字列を検索し、対応する数値を取得する。
せっかくなので自作関数にして、繰り返し呼び出せるようにしよう。
自作関数 例1:
@function str2num($val) {
$num-map: (
'0' : 0,
'1' : 1,
'2' : 2,
'3' : 3,
'4' : 4,
'5' : 5,
'6' : 6,
'7' : 7,
'8' : 8,
'9' : 9,
);
$tmp: map-get($num-map, $val);
@return $tmp;
}
関数名 str2num で引数をひとつ受け入れ $val に保存して処理する関数ができた。テストしてみよう。
$val: "1";
@debug "#{$val} = #{type-of($val)}";
$val: str2num($val);
@debug "#{$val} = #{type-of($val)}";
$val に文字列 ”1” を代入し、関数を呼び出してみる。
2行目と4行目の @debug は 同じことをしているが、3行目の str2num 関数実行の前後で型が変わったか確認するためのもの。
結果は以下のように、string と number を出力する。
> Debug: 1 = string
> Debug: 1 = number
上手く動いているようだが、このままでは引数に数値を渡したとき理想の結果を得ることができない。
$val: 1; // 数値型の値
@debug "#{$val} = #{type-of($val)}";
$val: str2num($val);
@debug "#{$val} = #{type-of($val)}";
> Debug: 1 = number
> Debug: = null
マップのキーが文字列なので、数値で検索してもヒットしないのだ。
str2num 関数を修正しよう。
元々数値なら変換する必要がないし、他の型も除外で良いだろう。
自作関数 例2:
@function str2num($val) {
@if number == type-of($val) {
@return $val;
} @else if string != type-of($val) {
@warn "#{$val} is not string.";
@return $val;
}
$num-map: (
'0' : 0,
'1' : 1,
'2' : 2,
'3' : 3,
'4' : 4,
'5' : 5,
'6' : 6,
'7' : 7,
'8' : 8,
'9' : 9,
);
$tmp: map-get($num-map, $val);
@return $tmp;
}
受け取った引数の型が数値型なら、そのまま $val をリターンして終了する。
文字列型以外なら $val を戻すとともに、 @warn で文字列じゃないよ、と注意を促す。
文字列型なら引き続き処理を進める。
$val: 1;
@debug "#{$val} = #{type-of($val)}";
$val: str2num($val);
@debug "#{$val} = #{type-of($val)}";
> Debug: 1 = number
> Debug: 1 = number
$val: #fff; // 色コード
@debug "#{$val} = #{type-of($val)}";
$val: str2num($val);
@debug "#{$val} = #{type-of($val)}";
> Debug: #fff = color
Warning: #fff is not string.
> Debug: #fff = color
もう一つ問題がある。
マップに登録したキー以外ではヒットしないから、文字列であっても 0~9 以外は戻り値が null になってしまう。
$val: a; // 文字列
@debug "#{$val} = #{type-of($val)}";
$val: str2num($val);
@debug "#{$val} = #{type-of($val)}";
> Debug: a = string
> Debug: = null
マップの検索処理を修正しよう。
自作関数 例3:
@function str2num($val) {
@if number == type-of($val) {
@return $val;
} @else if string != type-of($val) {
@warn "#{$val} is not string.";
@return $val;
}
$num-map: (
'0' : 0,
'1' : 1,
'2' : 2,
'3' : 3,
'4' : 4,
'5' : 5,
'6' : 6,
'7' : 7,
'8' : 8,
'9' : 9,
);
$tmp: map-get($num-map, $val);
@if not $tmp {
@warn "'#{$val}' is not string type numbers.";
$tmp: $val;
}
@return $tmp;
}
$tmp にマップの検索結果を代入しているが、見つからなければ null になるので、その場合は $val を代入しなおしている。
ついでに @warn で数字じゃなかったことを注意してみる。
$val: a; // 文字列
@debug "#{$val} = #{type-of($val)}";
$val: str2num($val);
@debug "#{$val} = #{type-of($val)}";
> Debug: a = string
Warning: 'a' is not string type numbers.
> Debug: a = string
これで一通り変換し、失敗する場合は理由が分かるようになった。
また、戻り値が null であること自体は構わないのだが、多くの場合 null という特殊な状態は処理に支障をきたす。わざわざ文字列を数値に変換するならその先に別の処理があると予想されるので、今回は元の値を残す方法を選択した。必ず数値を戻したいならゼロを代入するなど代替えもきく。
まとめ
今回作成した関数は 1桁の数字にしか対応していないため、残念ながらそのまま活用できる場面は少ないと思う。
一度に変換できる桁数を増やすには、1文字ずつ処理し、末尾が一の位、次が十の位となるよう繰り返し処理する必要がある。
長くなるので追加の処理はまた別記事にまとめたい。
続きはこちら