どう書く?org F# 数字混じり文字列ソート
「どう書く?org」http://ja.doukaku.org/に挑戦です。
さて今回の問題はこちら「数字混じり文字列ソート」http://ja.doukaku.org/295/
次のようなソードをおこなうソートを作れというものです。
辞書順ソート: 1.txt, 10.txt, 100.txt, 2.txt, 20.txt
数字混じり文字列ソート: 1.txt, 2.txt, 10.txt, 20.txt, 100.txt
例2:
辞書順ソート: x12, x13, x1A, x1B, xAB
数字混じり文字列ソート: x1A, x1B, x12, x13, xAB
例3:
辞書順ソート: A10B1, A10B10, A10B2, A1B1, A1B10, A1B2, A2B1, A2B10, A2B2
数字混じり文字列ソート: A1B1, A1B2, A1B10, A2B1, A2B2, A2B10, A10B1, A10B2, A10B10
正規表現を利用して、愚直に実装してみました。(コードが堅い!)
速度も望めません。
> open System
open System.Text.RegularExpressions
let numRemRegex = new Regex("(?<topNum>(^([\\d]+)))(?<topNumRem>(.*))")
let strRemRegex = new Regex("(?<topStr>(^([^\\d]+)))(?<topStrRem>(.*))")
let rec compStrIncNum (st_L:string) (st_R:string) =
let topNum_L = numRemRegex.Match(st_L).Groups.["topNum"]
let topNum_R = numRemRegex.Match(st_R).Groups.["topNum"]
let topStr_L = strRemRegex.Match(st_L).Groups.["topStr"]
let topStr_R = strRemRegex.Match(st_R).Groups.["topStr"]
if (topNum_L.Success && topNum_R.Success) then
let intCompVal = compare (Int64.Parse(topNum_L.Value)) (Int64.Parse(topNum_R.Value))
if intCompVal = 0 then
let TopNumRem_L = numRemRegex.Match(st_L).Groups.["topNumRem"]
let TopNumRem_R = numRemRegex.Match(st_R).Groups.["topNumRem"]
compStrIncNum TopNumRem_L.Value TopNumRem_R.Value
else
intCompVal
elif (topStr_L.Success && topStr_R.Success) then
let strCompVal = compare topStr_L.Value topStr_R.Value
if strCompVal = 0 then
let TopStrRem_L = strRemRegex.Match(st_L).Groups.["topStrRem"]
let TopStrRem_R = strRemRegex.Match(st_R).Groups.["topStrRem"]
compStrIncNum TopStrRem_L.Value TopStrRem_R.Value
else
compare st_L st_R
else
compare st_L st_R;;
val numRemRegex : System.Text.RegularExpressions.Regex =
(?<topNum>(^([\d]+)))(?<topNumRem>(.*))
val strRemRegex : System.Text.RegularExpressions.Regex =
(?<topStr>(^([^\d]+)))(?<topStrRem>(.*))
val compStrIncNum : string -> string -> int
実行例
> List.sortWith compStrIncNum ["100.txt"; "1.txt"; "20.txt"; "2.txt"; "10.txt"];;
val it : string list = ["1.txt"; "2.txt"; "10.txt"; "20.txt"; "100.txt"]
> List.sortWith compStrIncNum ["x13"; "x1B"; "xAB"; "x12"; "x1A"];;
val it : string list = ["x1A"; "x1B"; "x12"; "x13"; "xAB"]
> List.sortWith compStrIncNum ["A10B1";"A10B10";"A10B2";"A1B1";"A1B10";"A1B2";"A2B1";"A2B10";"A2B2"];;
val it : string list =
["A1B1"; "A1B2"; "A1B10"; "A2B1"; "A2B2"; "A2B10"; "A10B1"; "A10B2";"A10B10"]
> List.sortWith compStrIncNum ["う54う"; "い23い"; "い1い"; "あ9あ"; "う100う"; "あ88あ"];;
val it : string list = ["あ9あ"; "あ88あ"; "い1い"; "い23い"; "う54う"; "う100う"]
ただこれだとA006BとA6Bが等しいものとしてソートされるので、なにか規則を付け加えた方がよいかもしれません。
さて今回の問題はこちら「数字混じり文字列ソート」http://ja.doukaku.org/295/
次のようなソードをおこなうソートを作れというものです。
辞書順ソート: 1.txt, 10.txt, 100.txt, 2.txt, 20.txt
数字混じり文字列ソート: 1.txt, 2.txt, 10.txt, 20.txt, 100.txt
例2:
辞書順ソート: x12, x13, x1A, x1B, xAB
数字混じり文字列ソート: x1A, x1B, x12, x13, xAB
例3:
辞書順ソート: A10B1, A10B10, A10B2, A1B1, A1B10, A1B2, A2B1, A2B10, A2B2
数字混じり文字列ソート: A1B1, A1B2, A1B10, A2B1, A2B2, A2B10, A10B1, A10B2, A10B10
正規表現を利用して、愚直に実装してみました。(コードが堅い!)
速度も望めません。
> open System
open System.Text.RegularExpressions
let numRemRegex = new Regex("(?<topNum>(^([\\d]+)))(?<topNumRem>(.*))")
let strRemRegex = new Regex("(?<topStr>(^([^\\d]+)))(?<topStrRem>(.*))")
let rec compStrIncNum (st_L:string) (st_R:string) =
let topNum_L = numRemRegex.Match(st_L).Groups.["topNum"]
let topNum_R = numRemRegex.Match(st_R).Groups.["topNum"]
let topStr_L = strRemRegex.Match(st_L).Groups.["topStr"]
let topStr_R = strRemRegex.Match(st_R).Groups.["topStr"]
if (topNum_L.Success && topNum_R.Success) then
let intCompVal = compare (Int64.Parse(topNum_L.Value)) (Int64.Parse(topNum_R.Value))
if intCompVal = 0 then
let TopNumRem_L = numRemRegex.Match(st_L).Groups.["topNumRem"]
let TopNumRem_R = numRemRegex.Match(st_R).Groups.["topNumRem"]
compStrIncNum TopNumRem_L.Value TopNumRem_R.Value
else
intCompVal
elif (topStr_L.Success && topStr_R.Success) then
let strCompVal = compare topStr_L.Value topStr_R.Value
if strCompVal = 0 then
let TopStrRem_L = strRemRegex.Match(st_L).Groups.["topStrRem"]
let TopStrRem_R = strRemRegex.Match(st_R).Groups.["topStrRem"]
compStrIncNum TopStrRem_L.Value TopStrRem_R.Value
else
compare st_L st_R
else
compare st_L st_R;;
val numRemRegex : System.Text.RegularExpressions.Regex =
(?<topNum>(^([\d]+)))(?<topNumRem>(.*))
val strRemRegex : System.Text.RegularExpressions.Regex =
(?<topStr>(^([^\d]+)))(?<topStrRem>(.*))
val compStrIncNum : string -> string -> int
実行例
> List.sortWith compStrIncNum ["100.txt"; "1.txt"; "20.txt"; "2.txt"; "10.txt"];;
val it : string list = ["1.txt"; "2.txt"; "10.txt"; "20.txt"; "100.txt"]
> List.sortWith compStrIncNum ["x13"; "x1B"; "xAB"; "x12"; "x1A"];;
val it : string list = ["x1A"; "x1B"; "x12"; "x13"; "xAB"]
> List.sortWith compStrIncNum ["A10B1";"A10B10";"A10B2";"A1B1";"A1B10";"A1B2";"A2B1";"A2B10";"A2B2"];;
val it : string list =
["A1B1"; "A1B2"; "A1B10"; "A2B1"; "A2B2"; "A2B10"; "A10B1"; "A10B2";"A10B10"]
> List.sortWith compStrIncNum ["う54う"; "い23い"; "い1い"; "あ9あ"; "う100う"; "あ88あ"];;
val it : string list = ["あ9あ"; "あ88あ"; "い1い"; "い23い"; "う54う"; "う100う"]
ただこれだとA006BとA6Bが等しいものとしてソートされるので、なにか規則を付け加えた方がよいかもしれません。
スポンサーサイト