我一直在尝试创建一个过滤器,使用递归函数和匹配模式检查文本中是否存在短语列表中的短语,但不知何故似乎不起作用...也许有人可以给我提示为什么?
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()作为输出......
答案 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,但我想指出,它对子问题的划分已经非常充分;令人震惊的是缺乏相关的测试,以及针对每个子问题的各个函数的一些描述性命名。
如何直接命名(和测试)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 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