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

时间:2018-01-02 21:44:41

标签: 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 
                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"]

函数调用:检查p t

我已经修改了一些错误,但我已经编辑了我的问题,但是,对于这些列表,程序将unit()作为输出......

2 个答案:

答案 0 :(得分:3)

有一些提示:

  • function Connect-Exchange{ param( [Parameter(Position=0, Mandatory=$true)] [string]$MailboxName, [Parameter(Position=1, Mandatory=$true)] [System.Management.Automation.PSCredential]$Credentials, [Parameter(Position=2, Mandatory=$false)] [string]$url ) Begin { Load-EWSManagedAPI ## Set Exchange Version $ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2013 ## Create Exchange Service Object $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion) ## Set Credentials to use two options are availible Option1 to use explict credentials or Option 2 use the Default (logged On) credentials #Credentials Option 1 using UPN for the windows Account #$psCred = Get-Credential $creds = New-Object System.Net.NetworkCredential($Credentials.UserName.ToString(),$Credentials.GetNetworkCredential().password.ToString()) $service.Credentials = $creds #Credentials Option 2 #service.UseDefaultCredentials = $true #$service.TraceEnabled = $true ## Choose to ignore any SSL Warning issues caused by Self Signed Certificates Handle-SSL ## Set the URL of the CAS (Client Access Server) to use two options are availbe to use Autodiscover to find the CAS URL or Hardcode the CAS to use #CAS URL Option 1 Autodiscover if($url){ $uri=[system.URI] $url $service.Url = $uri } else{ $service.AutodiscoverUrl($MailboxName,{$true}) } Write-host ("Using CAS Server : " + $Service.url) #CAS URL Option 2 Hardcoded #$uri=[system.URI] "https://casservername/ews/exchange.asmx" #$service.Url = $uri ## Optional section for Exchange Impersonation #$service.ImpersonatedUserId = new-object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $MailboxName) if(!$service.URL){ throw "Error connecting to EWS" } else { return $service } } } function Load-EWSManagedAPI{ param( ) Begin { ## Load Managed API dll ###CHECK FOR EWS MANAGED API, IF PRESENT IMPORT THE HIGHEST VERSION EWS DLL, ELSE EXIT $EWSDLL = (($(Get-ItemProperty -ErrorAction SilentlyContinue -Path Registry::$(Get-ChildItem -ErrorAction SilentlyContinue -Path 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Exchange\Web Services'|Sort-Object Name -Descending| Select-Object -First 1 -ExpandProperty Name)).'Install Directory') + "Microsoft.Exchange.WebServices.dll") if (Test-Path $EWSDLL) { Import-Module $EWSDLL } else { "$(get-date -format yyyyMMddHHmmss):" "This script requires the EWS Managed API 1.2 or later." "Please download and install the current version of the EWS Managed API from" "http://go.microsoft.com/fwlink/?LinkId=255472" "" "Exiting Script." exit } } } function Handle-SSL{ param( ) Begin { ## Code From http://poshcode.org/624 ## Create a compilation environment $Provider=New-Object Microsoft.CSharp.CSharpCodeProvider $Compiler=$Provider.CreateCompiler() $Params=New-Object System.CodeDom.Compiler.CompilerParameters $Params.GenerateExecutable=$False $Params.GenerateInMemory=$True $Params.IncludeDebugInformation=$False $Params.ReferencedAssemblies.Add("System.DLL") | Out-Null $TASource=@' namespace Local.ToolkitExtensions.Net.CertificatePolicy{ public class TrustAll : System.Net.ICertificatePolicy { public TrustAll() { } public bool CheckValidationResult(System.Net.ServicePoint sp, System.Security.Cryptography.X509Certificates.X509Certificate cert, System.Net.WebRequest req, int problem) { return true; } } } '@ $TAResults=$Provider.CompileAssemblyFromSource($Params,$TASource) $TAAssembly=$TAResults.CompiledAssembly ## We now create an instance of the TrustAll and attach it to the ServicePointManager $TrustAll=$TAAssembly.CreateInstance("Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll") [System.Net.ServicePointManager]::CertificatePolicy=$TrustAll ## end code from http://poshcode.org/624 } } function Send-VoteMail { param( [Parameter(Position=0, Mandatory=$true)] [string]$MailboxName, [Parameter(Mandatory=$true)] [System.Management.Automation.PSCredential]$Credentials, [Parameter(Position=2, Mandatory=$false)] [switch]$useImpersonation, [Parameter(Position=3, Mandatory=$false)] [string]$url, [Parameter(Position=4, Mandatory=$false)] [string]$Subject, [Parameter(Position=5, Mandatory=$false)] [string]$Body, [Parameter(Position=6, Mandatory=$false)] [string]$To, [Parameter(Position=7, Mandatory=$false)] [psobject]$Verbs ) Begin { if($url){ $service = Connect-Exchange -MailboxName $MailboxName -Credentials $Credentials -url $url } else{ $service = Connect-Exchange -MailboxName $MailboxName -Credentials $Credentials } if($useImpersonation.IsPresent){ $service.ImpersonatedUserId = new-object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $MailboxName) } $EmailMessage = New-Object Microsoft.Exchange.WebServices.Data.EmailMessage -ArgumentList $service $VerbStreamProp = new-object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition([Microsoft.Exchange.WebServices.Data.DefaultExtendedPropertySet]::Common,0x8520, [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Binary) $VerbSettingValue = get-VerbStream -MessageClass IPM.Note -VerbArray $Verbs $EmailMessage.Subject = $Subject #Add Recipients $EmailMessage.ToRecipients.Add($To) $EmailMessage.Body = New-Object Microsoft.Exchange.WebServices.Data.MessageBody $EmailMessage.Body.BodyType = [Microsoft.Exchange.WebServices.Data.BodyType]::HTML $EmailMessage.Body.Text = $Body $EmailMessage.SetExtendedProperty($VerbStreamProp,(hex2binarray $VerbSettingValue)) $EmailMessage.SendAndSaveCopy() } } function get-VerbStream { [CmdletBinding()] param ( [Parameter(Position = 0, Mandatory = $true)] [string] $MessageClass, [Parameter(Position = 1, Mandatory = $true)] [psobject] $VerbArray ) Begin { $vCount = ($VerbArray.length + 4); $Header = "02010" + $vCount + "00000000000000"; $ReplyToAllHeader = "055265706C790849504D2E4E6F7465074D657373616765025245050000000000000000"; $ReplyToAllFooter = "0000000000000002000000660000000200000001000000"; $ReplyToHeader = "0C5265706C7920746F20416C6C0849504D2E4E6F7465074D657373616765025245050000000000000000"; $ReplyToFooter = "0000000000000002000000670000000300000002000000"; $ForwardHeader = "07466F72776172640849504D2E4E6F7465074D657373616765024657050000000000000000"; $ForwardFooter = "0000000000000002000000680000000400000003000000"; $ReplyToFolderHeader = "0F5265706C7920746F20466F6C6465720849504D2E506F737404506F737400050000000000000000"; $ReplyToFolderFooter = "00000000000000020000006C00000008000000"; $VoteOptionExtras = "0401055200650070006C00790002520045000C5200650070006C007900200074006F00200041006C006C0002520045000746006F007200770061007200640002460057000F5200650070006C007900200074006F00200046006F006C0064006500720000"; $DisableReplyAllVal = "00"; $DisableReplyAllVal = "01"; $DisableReplyVal = "00"; $DisableReplyVal = "01"; $DisableForwardVal = "00"; $DisableForwardVal = "01"; $DisableReplyToFolderVal = "00"; $DisableReplyToFolderVal = "01"; $OptionsVerbs = ""; $VerbValue = $Header + $ReplyToAllHeader + $DisableReplyAllVal + $ReplyToAllFooter + $ReplyToHeader + $DisableReplyVal + $ReplyToFooter + $ForwardHeader + $DisableForwardVal + $ForwardFooter + $ReplyToFolderHeader + $DisableReplyToFolderVal + $ReplyToFolderFooter; for ($index = 0; $index -lt $VerbArray.length; $index++) { $VerbValue += GetWordVerb -Word $VerbArray[$index] -Postion ($index + 1) -MessageClass $MessageClass $VbValA = convertToHexUnicode($VerbArray[$index]) $VbhVal = decimalToHexString($VerbArray[$index].length) $vbValB = convertToHexUnicode($VerbArray[$index]) $vbPos = decimalToHexString($VerbArray[$index].length) $OptionsVerbs += $vbPos + $VbValA + $VbhVal + $vbValB } $VerbValue += $VoteOptionExtras + $OptionsVerbs; return $VerbValue; } } function GetWordVerb { [CmdletBinding()] param ( [Parameter(Position = 0, Mandatory = $true)] [string] $Word, [Parameter(Position = 1, Mandatory = $true)] [decimal] $Postion, [Parameter(Position = 2, Mandatory = $true)] [psobject] $MessageClass ) Begin { $verbstart = "04000000"; $length = decimalToHexString($Word.length); $HexString = [System.BitConverter]::ToString([System.Text.UnicodeEncoding]::ASCII.GetBytes($Word)).Replace("-","") $mclength = decimalToHexString($MessageClass.length); $mcHexString = [System.BitConverter]::ToString([System.Text.UnicodeEncoding]::ASCII.GetBytes($MessageClass)).Replace("-","") $Option1 = "000000000000000000010000000200000002000000"; $Option2 = "000000FFFFFFFF"; $lo = decimalToHexString -number $Postion return ($verbstart + $length + $HexString + $mclength + $mcHexString + "00" + $length + $HexString + $Option1 + $lo + $Option2) ; } } function decimalToHexString { [CmdletBinding()] param ( [Parameter(Position = 1, Mandatory = $true)] [Int] $number ) Begin{ if ($number -lt 0) { $number = 0xFFFFFFFF + $number + 1; } $numberret = "{0:x}" -f $number if ($numberret.length -eq 1) { $numberret = "0" + $numberret; } return $numberret; } } function convertToHexUnicode { [CmdletBinding()] param ( [Parameter(Position = 1, Mandatory = $true)] [String] $str ) Begin{ $hex = [System.BitConverter]::ToString([System.Text.UnicodeEncoding]::Unicode.GetBytes($str)).Replace("-","") return $hex; } } function hex2binarray($hexString){ $i = 0 [byte[]]$binarray = @() while($i -le $hexString.length - 2){ $strHexBit = ($hexString.substring($i,2)) $binarray += [byte]([Convert]::ToInt32($strHexBit,16)) $i = $i + 2 } return ,$binarray }

    返回错误的结果
    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不是递归调用的,它调用check2并返回

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

更新

请注意,check并不真正返回任何值(它返回单位)。此外,它的功能与check2重叠 - 它会使用短语中的第一个单词检查头部,无论如何都是matchTails所做的。

matchTails也返回单位,()表示单位。

所以让我们重写check

check

答案 1 :(得分:0)

虽然问题现在已been basically answered,但我想指出,它对子问题的划分已经非常充分;令人震惊的是缺乏相关的测试,以及针对每个子问题的各个函数的一些描述性命名。

如何直接命名(和测试)matchTailscheck2check

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 rec startsWithPhrase phrase text = 
    match phrase, text with
    | h1::t1, h2::t2 when h1 = h2 -> startsWithPhrase t1 t2
    | [], _-> true
    | _ -> false

let rec containsPhrase phrase text =
    startsWithPhrase phrase text ||
    match text with
    | _::tl -> containsPhrase phrase tl
    | [] -> false

let rec containsAnyPhrase phrases text =
    match phrases with
    | h::tl -> 
        containsPhrase h text ||
        containsAnyPhrase tl text
    | [] -> false

完全使用高级函数可能要容易得多,每个函数都代替一个递归循环。虽然这里有一个略微不同的方法,将你的草堆分成针大小的切片,并将每个切片与给定的短语进行比较。

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