问题描述
我已经实现了如下斐波那契数列生成器
I have implemented a Fibonacci Sequence generator as follows
let getNext upperLimit current=
let (e1, e2) = current
let next = e1 + e2
if next > upperLimit then None
else Some (next, (e2,next))
let fib upperLimit = (0,1) |> Seq.unfold (getNext upperLimit) |> Seq.append [0;1]
我的测试代码是
[<Test>]
member Spec.``fib not exeeding 20 should be 0,1,1,2,3,5,8,13``()=
let expected = seq [0;1;1;2;3;5;8;13]
let result = fib 20
let expectedSameAsResult = (expected = result)
printfn "Expected: %A Result: %A result length: %d" expected result (Seq.length result)
Assert.That expectedSameAsResult
测试失败,打印结果为
预期:[0;1;1;2;3;5;8;13]结果:seq [0;1;1;2;...]结果长度:8
当我使用for循环打印结果中的每个元素时,我都按预期的顺序得到了完全相同的元素.
When I used a for loop to print every element in result, I got exact same elements in the expected sequence.
那么,期望序列和结果序列之间有什么区别?
So, what is the difference between the expected and result sequence?
可以在 https://github.com/weima/EulerProblems/tree/master中找到我的实现/EulerProblems
回答约翰·帕尔默的答案我刚刚在F#互动窗口中编写了一个测试
To answer John Palmer's answerI just wrote a test in F# interactive window
let a = seq[1;2;3]
let b = seq[1;2;3]
let c = a = b;;
我得到的结果是val a:seq = [1;2;3]val b:seq = [1;2;3]val c:bool = true
The result I got isval a : seq = [1; 2; 3]val b : seq = [1; 2; 3]val c : bool = true
所以F#也可以对序列进行结构比较.
So F# can do structural comparison to sequences too.
编辑以反映Gene Belitski的答案我已将测试更改为
[<Test>]
member Spec.``fib not exeeding 20 should be 0,1,1,2,3,5,8,13``()=
let expected = seq [0;1;1;2;3;5;8;13]
let result = Problem2.fib 20
let comparedResult = Seq.compareWith (fun a b -> a - b) expected result
let expectedSameAsResult = (comparedResult = 0)
Assert.That expectedSameAsResult
它现在可以工作了.谢谢!但是我仍然不明白为什么简单的seq [1; 2; 3] = seq [1; 2; 3]可以工作,但是我的测试用例却没有.
And it worked now. Thanks! but I still don't understand why a simple seq[1;2;3]=seq[1;2;3] works, but my test case doesn't.
推荐答案
尽管您可能希望 a = b
会比较实际上由 a = b
计算的序列的元素参考相等.
Whilst you may expect that a=b
would compare elements for sequences it infact a=b
computes reference equality.
您可以通过类似的方式看到此
You can see this with something like
seq {1..3} = seq {1..3}
返回false.
但是,在某些情况下,当您使用常量时,您会得到令人困惑的结果,尤其是
However, in some cases when you use constants you get confusing results, in particular
seq [1;2;3] = seq [1;2;3]
返回true,这很令人困惑.
returns true, which is confusing.
为避免此问题,您需要做类似的事情
To avoid this issue, you need to do something like
let test a b = Seq.fold (&&) true (Seq.zip a b |> Seq.map (fun (aa,bb) -> aa=bb))
在元素上进行比较.
或者,您可以使用Gene答案中概述的 Seq.compareWith
.但是,这要求元素还必须实现比较运算符以及相等性,对于某些事情,例如实现了 =
但不进行比较的区别联合,则可能并非如此.
Alternatively, you can use Seq.compareWith
as outlined in Gene's answer. However, this requires that the elements also implement a comparison operator as well as equality, which may not be the case for some things like discriminated unions which implement =
but not comparison.
这篇关于F#序列比较的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!