F#:测试两个字符串是否为字谜

F#:测试两个字符串是否为字谜,f#,F#,我是编程新手,F#是我的第一语言 这是我的密码: let areAnagrams (firstString: string) (secondString: string) = let countCharacters (someString: string) = someString.ToLower().ToCharArray() |> Array.toSeq |> Seq.c

我是编程新手,F#是我的第一语言

这是我的密码:

let areAnagrams (firstString: string) (secondString: string) =
    let countCharacters (someString: string) =
        someString.ToLower().ToCharArray() |> Array.toSeq
                                           |> Seq.countBy (fun eachChar -> eachChar)
                                           |> Seq.sortBy (snd >> (~-))
    countCharacters firstString = countCharacters secondString

let testString1 = "Laity"
let testString2 = "Italy"
printfn "It is %b that %s and %s are anagrams." (areAnagrams testString1 testString2) (testString1) (testString2)
这是输出:

俗人和意大利都是字谜,这是错误的


出了什么问题?我应该做哪些更改?

您的
countCharacters
实现仅使用第二个元素(每个字符的出现次数)对元组进行排序,但如果有多个字符出现相同次数,则不定义顺序

如果对两个示例运行
countCharacters
函数,则可以看到问题:

> countCharacters "Laity";;
val it : seq<char * int> = seq [('l', 1); ('a', 1); ('i', 1); ('t', 1); ...]
> countCharacters "Italy";;
val it : seq<char * int> = seq [('i', 1); ('t', 1); ('a', 1); ('l', 1); ...]
请注意,您实际上不需要
Seq.countBy
——因为如果您只对所有字符进行排序,它将同样有效(重复的字符将一个接一个)。所以你可以用:

let countCharacters (someString: string) =
    someString.ToLower() |> Seq.sort |> List.ofSeq

对两个字符串的字符进行排序提供了一个简单的解决方案,但这可能是递归的一个很好的例子

可以立即排除不同长度的字符串

您还可以通过使用空字符串替换每个迭代中出现的所有字符来过滤掉它们

let rec areAnagram (x:string) (y:string) =
    if x.Lenght  <> t.Lenght 
    then false else
    if x.Lenght = 0
    then true else 
    let reply = x.[0].ToString ()
    areAnagram
        (x.Replace (reply,""))
        (y.Replace (reply,""))
let rec arenagram(x:string)(y:string)=
如果x.长度t.长度
那就错了
如果x.长度=0
那就对了
让reply=x[0]。ToString()
面积图
(十)替换(答复“”)
(y.替换(答复“”)
对于许多用例,上面的操作应该比排序更快

无论如何,我们可以更进一步,将其转换为快速整数排序,而无需递归和字符串替换

let inline charToInt c = 
    int c - int '0'
let singlePassAnagram (x:string) =
    let hash : int array = Array.zeroCreate 100
    x |> Seq.iter (fun c->
    hash.[charToInt c] <- (hash.[charToInt c]+1)
    )  
let areAnagramsFast 
        (x:string) (y:string) =
    if x.Length <> y.Length
    then false else
    (singlePassAnagram x) = 
        (singlePassAnagram y)
让内联图表点c=
int c-int“0”
让单通道内存(x:string)=
让hash:int array=array.zeroCreate 100
x |>序列iter(乐趣c->

hash。[ChartPoint c]我认为还有一个问题,那就是对
seq
s的平等性测试不是结构化的。@kvb是的,我也刚刚意识到:)添加了!
let inline charToInt c = 
    int c - int '0'
let singlePassAnagram (x:string) =
    let hash : int array = Array.zeroCreate 100
    x |> Seq.iter (fun c->
    hash.[charToInt c] <- (hash.[charToInt c]+1)
    )  
let areAnagramsFast 
        (x:string) (y:string) =
    if x.Length <> y.Length
    then false else
    (singlePassAnagram x) = 
        (singlePassAnagram y)