代码之家  ›  专栏  ›  技术社区  ›  Podo

从列表f中删除#

  •  1
  • Podo  · 技术社区  · 7 年前

    今天晚上,我一直在用f#处理列表(创建、添加、搜索等),最近被一个列表项删除所困扰。代码非常简单。

    let menu = [("pizza",17);("hotdog",5);("burger", 12);("drink",3);
    ("milkshake",4)]
    
    //If key is in dictionary , return new dictionary with value removed
    //otherwise return dictionary unchanged
    let rec remove dict key =
        match dict with
        //if the list is empty, return an empty list
        | [] -> []
        //if the list is not empty and the head meets the removing criteria
        //return a list obtained by reiterating the algorithm on the tail
        //of the list
        | (k,v) :: tl when k = key -> tl :: remove tl key
        //if the list is not empty and the head does not meet the removing criteria
        //return a list obtained by appending the head to a list obtained by
        //reiterating algorithm on tail of the list 
        | (k,v) :: tl -> (k,v) :: remove tl key
    

    错误来自函数的最后一行, | (k,v) :: tl -> (k,v) :: remove tl key . 显然,它不认识 (k,v) 作为列表的开头,而只看到具有值的元组。这是有道理的,我不知道我还能期待什么,但问题是我不知道如何修复它。我试着把元组放在列表中,比如 [(k,v)] 但这让事情变得更糟。我甚至试过 | hd :: tl -> hd :: remove tl key 但我也有同样的问题。我编写的其他每个函数都在模式匹配中接受hd和tl作为列表。

    如何解决此问题?

    2 回复  |  直到 7 年前
        1
  •  5
  •   Gus    7 年前

    第二个守卫错了。您使用了两次尾部,并且由于您在cons操作中使用它作为第一个参数,因此它不会进行类型检查(它需要单个元素,而不是列表)。

    将其更改为:

    | (k,v) :: tl when k = key -> remove tl key
    
        2
  •  0
  •   rmunn    7 年前

    我看到了你正在犯的另一个错误。这是一个概念上的错误,而不是代码中的bug,但除非您理解错误,否则会导致更多bug。您写道:

    我编写的其他每个函数都接受hd和tl作为 列表 在我的模式匹配中。

    (我的重点)。你的错误是当你写作的时候 hd :: tl 二者都 hd tl 是列表。你说对了一半: tl公司 确实是该语法中的列表,但是 高清 是一个 单个项目 . 证明:

    let theList = [1; 2; 3; 4; 5]
    printfn "The list: %A" theList
    // Prints "The list: [1; 2; 3; 4; 5]"
    match theList with
    | [] -> printfn "The list was empty"
    | hd :: tl -> printfn "Head was %A and tail was %A" hd tl
    // Prints "Head was 1 and tail was [2; 3; 4; 5]"
    

    使用语法时 hd::tl 在模式匹配中,它将列表分为第一项(头部)和其余部分(尾部)。使用语法时 hd::tl 在普通表达式中(例如,任何不匹配模式的地方),您将获取一个名为 tl公司 和a 单个项目 打电话 高清 预编 将该项目添加到列表中,从而生成一个全新的列表,该列表的前面比以前的列表多了一个项目。

    如果你写了以下内容,我引用的句子应该是正确的:

    在我的模式匹配中,我编写的其他每个函数都接受tl作为列表,hd作为列表项。

    我希望这能帮助您更好地理解F#列表!