F#序列比较 [英] F# sequence comparison

查看:45
本文介绍了F#序列比较的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经实现了如下斐波那契数列生成器

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 answer I 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 is val 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#序列比较的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆