我正在研究一个F#程序,该程序读取文件并根据每一行的事件执行特定的操作。

例如,如果该行的第一个单词为create,则向列表中添加一个元素;如果删除,则从列表中删除一个元素;如果Modify,则修改列表中的值。

现在,我正在使用仅将processEventType函数应用于每行的map,但是我需要一种方法来继续处理相同的列表。

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


非常感谢任何帮助,因为我是函数式编程和F#的新手。

最佳答案

如果我正确理解了您的问题,那是processEventType不允许您一遍又一遍地使用相同的列表。如果您将事件应用于列表,则该事件的结果列表不会用于下一个事件。

由于您是SO的新手,因此我无法查看您的历史来确定您的知识库,因此无法为您提供相关思想的参考和指导。

基本上对于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


对于这个答案,当其他人正确使用像let rec这样的功能时,我将使用List.map;初剪只是个人喜好。我还可以使用|>对其进行大量重构,但是如果您想插入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


运行时,将产生以下输出:

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:

关于f# - 在F#中继续使用相同的列表,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36546669/

10-11 22:31
查看更多