String 如何检查文本中是否存在短语列表?

String 如何检查文本中是否存在短语列表?,string,list,text,f#,String,List,Text,F#,我一直在尝试创建一个过滤器,使用递归函数和匹配模式检查文本中是否存在短语列表中的短语,但不知何故,这似乎不起作用。。。也许有人能告诉我为什么 let rec matchTails (tail1 : string list) (tail2 : string list) = match tail1, tail2 with | h1::t1 , h2::t2 -> if (h1=h2) then matchTa

我一直在尝试创建一个过滤器,使用递归函数和匹配模式检查文本中是否存在短语列表中的短语,但不知何故,这似乎不起作用。。。也许有人能告诉我为什么

let rec matchTails (tail1 : string list) (tail2 : string list) = 
    match tail1, tail2 with
        | h1::t1 , h2::t2 -> 
            if (h1=h2) then 
                matchTails t1 t2
            else
                false
        | _, [] -> false
        | [],_-> true

let rec check2 (textH: string) (textT: string list) (phrases: string list list) = 
    match phrases with 
    |[] -> ()
    | h :: t ->
        printfn "%s -- %s" (h.Head) (textH)
        match h with
        |x when x.Length = 1 && x.Head = textH -> 
            ()
        |x when x.Head = textH && (matchTails (textT) (x)) ->
            printfn "%s" (x.Head)
        | _ -> ()
        check2 (textH) (textT) (t)

let rec check (phrases : string list list) (text:string list) = 
    match text with
    | [] -> ()
    | h :: t ->
        check2 (h) (t) (phrases)
        check phrases t


let p = [["rolex"]; ["free"; "spins"; "everyday"]; ["free"; "cash"]]

let t = ["hello";"and";"welcome";"to";"our";"annual";"free";"cash";"and";"rolex";"giveaway"]
函数调用:check p t

我编辑了我的问题,修正了一些错误,但是,有了这些列表,程序将unit()作为输出

这里有一些提示:

  • matchTails
    返回的结果不正确

    matchTails [ "asdf1" ] [ "asdf" ] => true
    matchTails [ "asdf" ] [ "asdf"; "asdf1" ] => true
    matchTails [ ] [ "" ] => true
    
    我怀疑在所有这些情况下,它都应该返回
    false
    。您想要的实现可能是:

    let rec matchTails (phrase : string list) (text : string list) = 
      match phrase, text with
      | h1 :: t1, h2 :: t2 -> if h1 = h2 then matchTails t1 t2
                              else false
      | [ ], _ -> true
      | _ -> false
    
    let matchTails_test () =
      if not (matchTails [ "" ] [ "" ]) then raise Exception()
      ...
    
  • check2
    不是递归调用的,因此只检查第一个短语

  • check
    不是递归调用的,它调用check2并返回

通常,尝试将问题分解为更小的函数,并分别测试每个函数。您正朝着正确的方向前进,缺少的是每个函数应该做什么和测试用例的清晰性

更新:

请注意,
check2
实际上并不返回任何值(它返回单位)。此外,它的功能与
matchTails
重叠-它用短语中的第一个单词检查头部,这就是
matchTails
的作用

检查也返回单位,()表示单位

让我们重写
检查

let rec check (phrases : string list list) (text : string list) =
  if phrases |> List.exists (fun ph -> matchTails ph text) then
    true
  else
    match text with
    | [] -> false
    | _ :: tail -> check phrases tail

虽然问题现在已经解决了,但我想指出,将其划分为子问题已经非常充分;令人震惊的是缺乏相关的测试,以及处理每个子问题的单个函数的一些描述性命名

例如,命名(和测试)
matchTails
check2
check
怎么样

let ps = [["rolex"]; ["free"; "spins"; "everyday"]; ["free"; "cash"]]
let t = ["hello";"and";"welcome";"to";"our";"annual";"free";"cash";"and";"rolex";"giveaway"]

startsWithPhrase ["hello"; "and"] t
containsPhrase ["free"; "cash"] t
containsAnyPhrase ps t
扰流板:


完全使用高级函数(每个函数代替一个递归循环)可能会容易得多。尽管这里的方法稍有不同,将干草堆分成针状大小的薄片,并将每一片与给定的短语进行比较

let containsPhraseHL phrase text = 
    Seq.windowed (List.length phrase) text
    |> Seq.exists (Seq.forall2 (=) phrase)

containsPhraseHL ["free"; "cash"] t

let containsAnyPhraseHL phrases text =
    List.exists (fun phrase -> containsPhraseHL phrase text) phrases

containsAnyPhraseHL ps t

在匹配表达式中有
h2=h2
。这将始终评估为真。你的意思是
h1=h2
?我已经编辑了我的问题,并修复了那些错误,但程序似乎找到了长度为1的短语,而不是更长的短语。。
let containsPhraseHL phrase text = 
    Seq.windowed (List.length phrase) text
    |> Seq.exists (Seq.forall2 (=) phrase)

containsPhraseHL ["free"; "cash"] t

let containsAnyPhraseHL phrases text =
    List.exists (fun phrase -> containsPhraseHL phrase text) phrases

containsAnyPhraseHL ps t