主 - 细节场景.永远都在.好吧,如果不是永远的话,至少我在70年代的打卡上用FORTRAN做了大师级细节.它仍然存在 - 关于STO的大量细节问题.
我找了一个很好的方法在F#中做一个主细节识别器,没找到它.抱歉,如果我错过了,如果是这样,有人可以回复sto线程或网址吗?谢谢
这是我的F#-newbie在F#中做一个主细节识别器.即:将原始细节字符串的原始/平面列表减少为F#-records列表,其中主字符串与其详细字符串列表配对.
不在这里寻找高尔夫代码.优雅.我曾希望最终得到优雅的东西,但下面只是一个直接的递归列表步行.我的F#-newbie大脑未能看到如何在这里好好利用折叠,理解,折叠,地图,活动模式,计算表达式等.
让它保持在F#中可以做到的事情.如果在.Net中有一个预先构建的平面文件主 - 详细XML数据加载器,它可以在一行.Net调用中将master-detail .txt文件转换为.Net XML,这非常有趣,因为它可以用于F#.
作为一个有着长期命令式编程历史的人,我试图坚持使用不可变的F#进行练习.但是如果在F#中使用命令式或可变代码真的是最好的方法,请解释一下.输出可以是元组列表,记录序列,元组数组等.
任何意见/反馈....谢谢
let testInput =
["master Homer" ; "Doh.."; "Doh!!" ;
"master Has none" ;
"master JoyJoyJoy"; "Yaa!" ; "Yaa!!!"; "Yaa!!!!!!"]
type md = {m: string; d: string list}
member x.addDetail newd = {m = x.m; d = x.d @ [newd]}
static member noMaster = {m = "" ; d = []} // master records can never be null-strings, so "" works here
static member isMaster (L:string) = L.StartsWith("master ")
static member isDetail (L:string) = not (md.isMaster L) // There is no third kind of record - if not a master then it is a detail
let rec masterDetails flatList currentMaster =
if md.noMaster = currentMaster then
match flatList with
| [] -> [] // If no master and no more input: input list was empty and the empty list is the overall result
| h :: t -> if md.isMaster h then // If no master, then head becomes the first master of the run
masterDetails t {m = h; d = []}
else
failwith "Bad input: First record must be a master record"
else
match flatList with
| [] -> [currentMaster] // End of input; return current master as a one-entry-list
| h :: t -> if md.isMaster h then // Head will now replace the current master as the new master
[currentMaster] @ masterDetails t {m = h; d = []}
else // Keep current master; and add detail record to current master's detail list
masterDetails t (currentMaster.addDetail h)
let testSolution = // Required: 1) Preserve order of the master sets. 2) Preserve sort order of details-within-masters.
[{m = "master Homer" ; d = ["Doh.."; "Doh!!" ]};
{m = "master Has none" ; d = [ ]};
{m = "master JoyJoyJoy"; d = ["Yaa!"; "Yaa!!!"; "Yaa!!!!!!"]} ]
let tryIt = masterDetails testInput md.noMaster
let testTry = (tryIt = testSolution)
Run Code Online (Sandbox Code Playgroud)
这听起来像是一份工作takeDrop
.
// split a list into a prefix of elements that all
// meet predicate 'p', and the suffix remainder
let takeDrop p l =
let rec loop acc l =
match l with
| h::t when p h -> loop (h::acc) t
| _ -> List.rev acc, l
loop [] l
let rec masterDetail input =
[match input with
| [] -> ()
| h::t ->
assert(md.isMaster h)
let det, rest = takeDrop (not << md.isMaster) t
yield { m = h; d = det }
yield! masterDetail rest]
Run Code Online (Sandbox Code Playgroud)
完整的测试代码如下.
let testInput =
["master Homer" ; "Doh.."; "Doh!!" ;
"master Has none" ;
"master JoyJoyJoy"; "Yaa!" ; "Yaa!!!"; "Yaa!!!!!!"]
type md = {m: string; d: string list}
static member isMaster (s:string) = s.StartsWith("master ")
let testSolution = // Required: 1) Preserve order of the master sets.
// 2) Preserve sort order of details-within-masters.
[{m = "master Homer" ; d = ["Doh.."; "Doh!!" ]};
{m = "master Has none" ; d = [ ]};
{m = "master JoyJoyJoy"; d = ["Yaa!"; "Yaa!!!"; "Yaa!!!!!!"]} ]
// split a list into a prefix of elements that all
// meet predicate 'p', and the suffix remainder
let takeDrop p l =
let rec loop acc l =
match l with
| h::t when p h -> loop (h::acc) t
| _ -> List.rev acc, l
loop [] l
let rec masterDetail input =
[match input with
| [] -> ()
| h::t ->
assert(md.isMaster h)
let det, rest = takeDrop (not << md.isMaster) t
yield { m = h; d = det }
yield! masterDetail rest]
let briSol = masterDetail testInput
printfn "%A" (briSol = testSolution)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
256 次 |
最近记录: |