F# 在F中继续使用相同的列表#
我正在开发一个F#程序,它读取文件并根据每行的事件执行特定的操作 例如,如果行中的第一个单词是create,我向列表中添加一个元素;如果是delete,我从列表中删除一个元素;如果modify,我修改列表中的值 现在我正在使用map,它只对每一行应用processEventType函数,但我需要一种方法来继续处理相同的列表F# 在F中继续使用相同的列表#,f#,functional-programming,F#,Functional Programming,我正在开发一个F#程序,它读取文件并根据每行的事件执行特定的操作 例如,如果行中的第一个单词是create,我向列表中添加一个元素;如果是delete,我从列表中删除一个元素;如果modify,我修改列表中的值 现在我正在使用map,它只对每一行应用processEventType函数,但我需要一种方法来继续处理相同的列表 let processEventType (words:string[]) myList = match words with | [| event; va
let processEventType (words:string[]) myList =
match words with
| [| event; var1; var2; var3 |] when event = "create" -> Map.add var2 var3 myList
| [| event; var1; var2; |] when event = "delete" -> Map.remove "2" myList
| _ -> failwith "Error processing event"
let test (lines: list<string>) =
List.map (fun line -> (processEventType(splitLine line) myList)) lines
let processEventType(words:string[])myList=
用词搭配
|[| event;var1;var2;var3 |]当event=“create”->Map.add var2 var3 myList
|[| event;var1;var2;|]当event=“delete”->Map.remove“2”myList时
|->failwith“错误处理事件”
let测试(行:列表)=
List.map(有趣的行->(processEventType(拆分行)myList))行
非常感谢您的帮助,因为我是函数式编程和F#的新手。如果我正确理解了您的问题,那就是
processEventType
不允许您反复使用相同的列表。如果将事件应用于列表,则该事件的结果列表不会用于下一个事件
因为你是新手,所以我无法查看你的历史来确定你的知识库,所以我不能给你相关想法的参考和指针
基本上,对于processEventType
,您需要返回列表(newList
),作为每个模式匹配的最终语句
// Signature of processEventType
val processEventType : string * string list -> theList:string list -> string list
然后在调用processEventType
的函数中获取该结果,并使用递归函数将其传递回processEventType
let rec processEvents commands theList =
match commands with
| (command::t) ->
let newList = processEventType command theList
processEvents t newList
| [] -> theList
对于这个答案,当其他人正确使用类似于List.map的函数时,我将使用let rec
;这只是个人的喜好,第一次剪。我还可以使用|>
对它进行重构,但如果您想插入printfn
以查看发生了什么,或者使用调试器,请不要对它进行分解
代码比您拥有的要大得多,因为使用F#immutable list
允许我按说明传递结果,因此我对输入进行了更多的处理,并添加了一些函数来处理列表中的数据
namespace Workspace
module main =
[<EntryPoint>]
let main argv =
let theList = []
let input : string =
"add 1 2 3 4" + System.Environment.NewLine +
"delete 1 2" + System.Environment.NewLine +
"add 1" + System.Environment.NewLine +
"delete 4 2" + System.Environment.NewLine +
"modify 1 5" + System.Environment.NewLine
let lines = input.Split([| '\n';'\r' |])
let lines = List.ofArray lines
let lines = List.filter (fun (x : string) -> x.Length > 0) lines
let commands = List.map(fun (line:string) -> line.Split([| ' ' |])) lines
let commands = List.map(List.ofArray) commands
let convertCommand (input : string list) : (string * string list) =
let command = List.head input
let values = List.tail input
(command,values)
let commands = List.map(convertCommand) commands
let rec merge master items =
match master,items with
| [],l | l,[] -> l
| x::xs', y::ys' ->
if x = y then x :: (merge xs' ys')
elif x < y then x :: (merge xs' items)
else y :: (merge master ys')
let deleteItems master items =
let deleteItem master item =
let rec deleteItem master item acc =
match master with
| (h::t) when h <> item ->
let acc = h :: acc
deleteItem t item acc
| (h::t) ->
deleteItem t item acc
| [] -> List.rev acc
deleteItem master item []
let rec deleteItemsInner master items =
match items with
| (item::t) ->
let master = deleteItem master item
deleteItemsInner master t
| [] -> master
deleteItemsInner master items
let modifyItems master v1 v2 =
let rec modifyInner master v1 v2 acc =
match master with
| (h::t) when h = v1 ->
let acc = v2 :: acc
modifyInner t v1 v2 acc
| (h::t) ->
let acc = h :: acc
modifyInner t v1 v2 acc
| [] -> List.rev acc
modifyInner master v1 v2 []
let processEventType (event : (string * string list)) (theList : string list) : string list =
let (command,eventValues) = event
match command with
| "add" ->
printfn "Adding: %A" eventValues
let newList = merge theList eventValues
printfn "result: %A" newList
newList
| "delete" ->
printfn "Deleting: %A" eventValues
let newList = deleteItems theList eventValues
printfn "result: %A" newList
newList
| "modify" ->
match eventValues with
| v1::v2::[] ->
printfn "Modifying: %A %A" v1 v2
let newList = modifyItems theList v1 v2
printfn "result: %A" newList
newList
| _ -> failwith "Error with modify parameters"
| _ -> failwith "Error processing event"
let rec processEvents commands theList =
match commands with
| (command::t) ->
let newList = processEventType command theList
processEvents t newList
| [] -> theList
let newList = processEvents commands theList
printfn "theList: %A" newList
printf "Press any key to exit: "
System.Console.ReadKey() |> ignore
printfn ""
0 // return an integer exit code
这里的问题到底是什么?如果我理解正确的话,他的问题是processEventType没有返回一个可以重新传递以供重用的列表。可能您正在寻找初始映射状态为
map.empty
的list.map
。但我猜得很疯狂,因为我不知道很多标识符应该是什么意思。将此问题重新表述为一个或多个简单的问题可能会有用,在这些问题中,输入、所用值的含义和所需结果都很清楚。@VandroyList.fold
正是我想要的,谢谢!非常感谢你!我没想到会有这样的回答。我决定使用List.fold
。但这就是我的问题的意思,如何递归地保持processEventType返回的列表
Adding: ["1"; "2"; "3"; "4"]
result: ["1"; "2"; "3"; "4"]
Deleting: ["1"; "2"]
result: ["3"; "4"]
Adding: ["1"]
result: ["1"; "3"; "4"]
Deleting: ["4"; "2"]
result: ["1"; "3"]
Modifying: "1" "5"
result: ["5"; "3"]
theList: ["5"; "3"]
Press any key to exit: