LoginSignup
1
2

More than 3 years have passed since last update.

Elmで int -> 3桁区切り文字列 の変換をする

Last updated at Posted at 2019-10-17

やりたいこと

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する必要があるのでエレガントではないかも)
one-line.elm
String.join "," (List.reverse (String.Extra.break 3 (String.reverse)))
impl.elm
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"

1
2
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2