やりたいこと
elmで 1234567890 みたいなintを 1,234,567,890 のように、読みやすく,を打ったStringに変換したい
コメントでコードを紹介いただきました
(2020-03-21 追記)
コメントで @SuzumiyaAoba さんに書いていただいたコードの方が綺麗なので、こちらを利用いただいた方が良いかと思います。確かに割り算する意味なかった。。。
https://qiita.com/miyatsuki/items/1db2540c118ea0d1b3cd#comment-e9f244959b0566ec1a6a
また、メモリ消費量(スタックフレーム)の観点でもこちらの方が有利とのことです。
参考・末尾再帰の最適化: https://qiita.com/pebblip/items/cf8d3230969b2f6b3132
(2020-03-21 追記2)
さらに話が進み、より汎用的なパターンとして下記2つを提示いただきました。
https://qiita.com/miyatsuki/items/1db2540c118ea0d1b3cd#comment-d3785141a58867d02cbb
- String-Extraのライブラリを使ったパターン(ただし2回reverseする必要があるのでエレガントではないかも)
String.join "," (List.reverse (String.Extra.break 3 (String.reverse)))
- ↑でも使っているString-Extraのbreakと同じ感じで実装したパターン
https://package.elm-lang.org/packages/elm-community/string-extra/latest/String-Extra
breakRight : Int -> String -> List String
breakRight width string =
if width == 0 || string == "" then
[ string ]
else
breakerRight width string []
breakerRight : Int -> String -> List String -> List String
breakerRight width string acc =
case string of
"" ->
acc
_ ->
breakerRight width
(String.dropRight width string)
(String.right width string :: acc)
thousandSeparator : Int -> String
thousandSeparator num =
String.join "," (breakRight 3 (String.fromInt num))
定義 (もともとこの記事で解として記載していたコード)
(多分使わない方がいいと思いますが、一応残しておきます)
--- 追記(20191020): 公式でpadleft関数が用意されてたのでそちらを使うようにする
--- zeroPadding 0埋めしたい数字 桁数
-- zeroPadding : Int -> Int -> String
-- zeroPadding num digit =
-- String.right 3 ("000" ++ String.fromInt num)
--- toIntString 桁区切りしたい数字 False
--- 第二引数にTrueを渡すと一番最後にも,がついてしまう
toIntString : Int -> Bool -> String
toIntString num addsLastComma =
let
comma : String
comma =
if addsLastComma then
","
else
""
in
if num >= 1000 then
toIntString (num // 1000) True ++ (String.padLeft 3 '0' (String.fromInt (modBy 1000 num))) ++ comma
else
String.fromInt (modBy 1000 num) ++ comma
使い方
--- 桁区切り: 1234567890 -> 1,234,567,890
toIntString 1234567890 False
--- 0埋め 12 -> 0012
zeroPadding 12 4
動きの例
入力として、1234567890
が与えられたとすると、次のような処理が再帰的に動く
toIntString 1234567890 False
= (toIntString 1234567 True) ++ (padLeft 3 '0' "890")
= ((toIntString 1234 True) ++ "," ++ (padLeft 3 '0' "567")) ++ (padLeft 3 '0' "890")
= (((toIntString 1 True) ++ (padLeft 3 '0' "234")) ++ "," ++ (padLeft 3 '0' "567")) ++ (padLeft 3 '0' "890")
= (((String.fromInt 1) ++ "," ++ (padLeft 3 '0' "234")) ++ "," ++ (zeroPadding 567 3)) ++ (padLeft 3 '0' "890")
= "1,234,567,890"