F#中的停止字删除

  • 本文关键字:删除 f# f#-scripting
  • 更新时间 :
  • 英文 :


我正试图写一段代码来删除字符串列表中的"the"、"this"等停止字。

我写了这个代码:

let rec public stopword (a : string list, b :string list) =
    match [a.Head] with
        |["the"]|["this"] -> stopword (a.Tail, b)
        |[] -> b
        |_ ->  stopword (a.Tail, b@[a.Head])

我在互动中运行了这个:

stopword (["this";"is";"the"], []);;

我得到了这个错误:

This expression was expected to have type string list but here has type 'a * 'b

F#中的Match表达式非常强大,尽管最初中的语法很混乱

你需要这样匹配列表:

let rec stopword a =
    match a with
    |"the"::t |"this"::t -> stopword t
    |h::t ->h::(stopword t)
    |[] -> []

实际错误是由于函数需要一个元组参数。你必须用调用函数

let result = stopword (["this";"is";"the"], [])

编辑:由于原问题已更改,上述答案不再有效;实际函数中的逻辑错误是,您最终得到的是一个带有尾部的单个元素列表,结果是一个空列表。在下一次递归调用中,函数在尝试获取此空列表的头部时阻塞

然而,函数本身并没有正确实现,而且比必要的要复杂得多。

let isNoStopword (word:string) =
    match word with
    | "the"|"this" -> false
    | _ -> true
let removeStopword (a : string list) =
    a |> List.filter(isNoStopword)
let test = removeStopword ["this";"is";"the"]

其他人已经提到了模式匹配在这种情况下的威力。在实践中,您通常有一组要删除的停止语。when防护使我们能够非常自然地进行模式匹配:

let rec removeStopwords (stopwords: Set<string>) = function
    | x::xs when Set.contains x stopwords -> removeStopwords stopwords xs 
    | x::xs -> x::(removeStopwords stopwords xs)
    | [] -> []

这个函数和@John的答案的问题在于它们不是尾递归的。它们在一个由几个停止语组成的长列表中用完了。在列表模块中使用尾部递归的高阶函数是一个好主意:

let removeStopwords (stopwords: Set<string>) xs =
    xs |> List.filter (stopwords.Contains >> not)

相关内容

  • 没有找到相关文章

最新更新