2011-03-29 41 views
1

是否有一个内置函数可以执行以下操作?使用自定义比较函数构建列表的等式?

let rec listsEqual xl yl f = 
    match xl, yl with 
    | [], [] -> true 
    | [], _ | _, [] -> false 
    | xh::xt, yh::yt -> if f xh yh then listsEqual xt yt f else false 

更新,进一步阐述:和一般的有什么办法在挖掘结构性比较,但使用自定义的比较函数?

+0

您是否在寻找Seq.compareWith功能? – Alex 2011-03-29 13:50:17

+0

@Alex - 不完全是,两个问题1)期望两个序列是相同类型的,2)不会短路(我认为)。 – 2011-03-29 14:21:06

回答

2

关于Seq.compareWith,你写道:

不大,两个问题1)预计 两个序列是相同类型的,2) 不短路

2)是错误的,这个功能确实是一个法院巡回。 1)是真的。从F#库取Seq.compareWith,修改(或删除)类型注释,它将适用于不同类型的序列。现在

[<CompiledName("CompareWith")>] 
let compareWith (f:'T1 -> 'T2 -> int) (source1 : seq<'T1>) (source2: seq<'T2>) = 
      //checkNonNull "source1" source1 
      //checkNonNull "source2" source2 
      use e1 = source1.GetEnumerator() 
      use e2 = source2.GetEnumerator() 
      let rec go() = 
       let e1ok = e1.MoveNext() 
       let e2ok = e2.MoveNext() 
       let c = (if e1ok = e2ok then 0 else if e1ok then 1 else -1) 
       if c <> 0 then c else 
       if not e1ok || not e2ok then 0 
       else 
        let c = f e1.Current e2.Current 
        if c <> 0 then c else 
        go() 
      go() 

,您可以发送电子邮件至fsbugs(@ microsoft.com),并要求他们删除该类型的约束在未来的F#版本。

+0

+1 @Laurent - 感谢您澄清“Seq.compareWith”的行为,错误已提交。 – 2011-03-29 22:09:30

+1

@Larent - 仅供参考我通过fsbugs与Brian进行了交流,在这个问题上不会有任何行动。 compareWith这个比较函数是为了捕获一个形式化的比较概念,所以'f a b = f b a',如果'a'和'b'是不同的类型,这是不可能的。 – 2011-04-20 15:15:17

3
List.forall2 : (('a -> 'b -> bool) -> 'a list -> 'b list -> bool) 

但它在列表之前需要f。您可以创建如下功能:

let listsEqual x y f = 
    if List.length x = List.length y then 
     List.forall2 f x y 
    else 
     false 

请记住,List.forall2假定长度相同。

+0

不错,非常接近。但我真的希望有一些实用程序模块可以让你做“与自定义比较器的结构比较”。 – 2011-03-29 12:37:51

+2

这个实现的一个潜在的性能问题是使用需要遍历整个列表的List.length。 – 2011-03-29 12:53:29

相关问题