F# 使用自定义比较函数的内置列表相等?
是否有执行以下操作的内置函数F# 使用自定义比较函数的内置列表相等?,f#,F#,是否有执行以下操作的内置函数 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 更新,进一步细化:一般来说,除了使用自定义比较功能外,是否有其他方法可以进行结构比较 List.forall
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
更新,进一步细化:一般来说,除了使用自定义比较功能外,是否有其他方法可以进行结构比较
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
假设长度相同
但是在列表之前需要f。您可以这样创建函数:
let listsEqual x y f =
if List.length x = List.length y then
List.forall2 f x y
else
false
请记住,
List.forall2
假设长度相同。关于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()
[]
让我们与(f:'T1->'T2->int)进行比较(source1:seq)=
//选中非空的“source1”source1
//checkNonNull“source2”source2
使用e1=source1.GetEnumerator()
使用e2=source2.GetEnumerator()
放手
设e1ok=e1.MoveNext()
设e2ok=e2.MoveNext()
设c=(如果e1ok=e2ok,则0 else如果e1ok,则1 else-1)
如果是c0,那么是c
如果不是e1ok | |不是e2ok,则为0
其他的
设c=f e1.电流e2.电流
如果是c0,那么是c
去()
go()
现在,您可以向fsbug(@microsoft.com)发送电子邮件,要求他们在下一个F#release中删除类型限制。关于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()
[]
让我们与(f:'T1->'T2->int)进行比较(source1:seq)=
//选中非空的“source1”source1
//checkNonNull“source2”source2
使用e1=source1.GetEnumerator()
使用e2=source2.GetEnumerator()
放手
设e1ok=e1.MoveNext()
设e2ok=e2.MoveNext()
设c=(如果e1ok=e2ok,则0 else如果e1ok,则1 else-1)
如果是c0,那么是c
如果不是e1ok | |不是e2ok,则为0
其他的
设c=f e1.电流e2.电流
如果是c0,那么是c
去()
go()
现在,您可以向fsbugs(@microsoft.com)发送电子邮件,要求他们在下一个F#release中删除类型限制。nice,非常接近。但我真的希望有一些实用模块,可以让你“与自定义比较器进行结构比较”。这个实现的一个潜在性能问题是使用List.length,它需要遍历整个列表。很好,非常接近。但我真的希望有一些实用模块可以让你“与自定义比较器进行结构比较”。这个实现的一个潜在性能问题是使用List.length,它需要遍历整个列表。你是在寻找Seq.compareWith函数吗?@Alex-不完全是,两个问题1)期望两个序列属于同一类型,2)没有短路(我想)。您正在寻找Seq.compareWith函数吗?@Alex-不完全是,两个问题1)期望两个序列属于同一类型,2)没有短路(我想)。+1@Laurent-感谢您澄清
Seq.compareWith
的行为,错误已提交。@Larent-仅供参考,我通过fsbugs与Brian进行了交谈,不会就此问题采取任何行动。比较函数compareWith
用于捕获比较的形式概念,以便fab=fa
,如果a
和b
是不同类型的,这是不可能的。+1@Laurent-感谢澄清Seq.compareWith
的行为,错误已提交。@Larent-仅供参考,我通过fsbugs与Brian进行了交谈,不会就此问题采取任何行动。比较函数compareWith
用于捕获比较的形式概念,以便fab=fa a
,如果a
和b
属于不同类型,则不可能实现这一点。