2012-02-23 19 views
0

我想写一个代码删除,如“了”,“这个”,在一个字符串列表等停用词去除F#

我写了这个代码停用词:

let rec public stopword (a : string list, b :string list) = 

    match [a.Head] with 
     |["the"]|["this"] -> stopword (a.Tail, b) 
     |[] -> b 
     |_ -> stopword (a.Tail, [email protected][a.Head]) 

我跑这在互动:

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

我得到这个错误:

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

在F#个

回答

4

匹配表达式是非常强大的,虽然语法在第一

迷惑你需要匹配列表,像这样:

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

万分感谢!!!!!!这个很有效。我希望我能在几个月内写下这段代码:) – codious 2012-02-23 09:31:14

2

实际的错误是由于功能期待一个元组参数。你将不得不调用与功能:

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"] 
+0

感谢您的实施。我用我的代码尝试了你的建议。它给出了这样的错误:预计这种表达有型 字符串列表 但这里有类型 “A *” B – codious 2012-02-23 09:40:29

+0

@SiddharthaChatterjee - 地方你已经错 – 2012-02-23 09:47:29

+1

插入逗号@SiddharthaChatterjee我改变了功能,只需要一个列表作为参数而不是包含两个列表的元组(如John Palmer)。这两个代码块是相互独立的。首先是你应该如何调用你的函数,第二是我的解决方案,包括“测试”变量的结果。 – Dirk 2012-02-23 09:55:48

2

其他人在这种情况下提到了模式匹配的力量。在实践中,你通常会有一系列要删除的停用词。而when后卫可以让我们的模式匹配很自然:

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

使用此功能,并@约翰的回答的问题是,他们不是尾递归。他们在一长串名单中用尽了一堆词组。这是一个好主意,用高阶函数List module这是尾递归:

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

谢谢你揭露这个问题的时候。很高兴听到各种方法来解决问题。 – codious 2012-02-23 14:06:24