首页 > 解决方案 > 使用元组列表定义模式匹配函数时出现 F# 异常错误

问题描述

我想创建一个函数来比较 2 个元组列表并返回在两个列表中匹配的元组元素。

到目前为止,我已经这样定义了我的函数:

let rec matchNames l1 l2  = 
    match (l1,l2) with
    | (n1,_,_) :: l1' , (n2,_,_)  :: l2' when n1 = n2 -> n1 :: matchNames l1' l2' 
    | _,_ -> failwith "error"

假设我有 2 个列表:

let l1 = [("Name1",1,2);("Name2",2,2)]
let l2 = [("Name2",3,2);("Name1",1,2);("Name3",1,1)]

当我将这些列表应用于我的函数时,它会触发我的失败异常:

System.Exception: error
  at FSI_0457.matchNames[0,1,2,3,4] (Microsoft.FSharp.Collections.FSharpList`1[T] l1, Microsoft.FSharp.Collections.FSharpList`1[T] l2) [0x000b7] in <f035af7fb206481ab722b92b2672833a>:0 
  at <StartupCode$FSI_0458>.$FSI_0458.main@ () [0x0000a] in <f035af7fb206481ab722b92b2672833a>:0 
  at (wrapper managed-to-native) System.Reflection.RuntimeMethodInfo.InternalInvoke(System.Reflection.RuntimeMethodInfo,object,object[],System.Exception&)
  at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x0006a] in <b18e5763ec3f41e68a8fe16d7f5e0bee>:0 
Stopped due to error

所以很明显我的例外没有正确定义。任何有关如何定义的建议或参考表示赞赏。

以防万一, matchNames l1 l2的预期结果应该是:

["Name1";"Name2"]

标签: f#

解决方案


我想出了几乎可以接受的答案:

let rec matchNames l1 l2  = 
    match (l1,l2) with
    | (n1,_,_) :: l1' , (n2,_,_)  :: l2' when n1 = n2 -> n1 :: matchNames l1' l2' 
    | (n1,_,_) :: l1' , (n2,_,_)  :: l2' when n1 <> n2 -> []
    | _,_ -> []

几乎,如果它们在两个列表中的索引相同,则该函数仅匹配这些名称。

例如:

let l1 = [("Name1",1,2);("Name2",2,2)]
let l2 = [("Name2",3,2);("Name1",1,2);("Name3",1,1)]

matchNames l1 l2 

有一个空列表的输出

但是如果我相应地定义 l1 和 l2

let l1 = [("Name1",1,2);("Name2",2,2)]
let l2 = [("Name1",3,2);("Name2",1,2);("Name3",1,1)]

它并不完美,但目前可以使用,如果有人有一个不依赖于匹配列表索引的解决方案,那么如果您在此处发布它将不胜感激。:)


推荐阅读