F#:如何测试序列/列表元素的相等性?

时间:2019-04-17 06:24:26

标签: f#

我想测试列表/序列中的所有元素是否都等于

例如,整数序列。

我想测试序列中的ALL元素是否等于相同的数字。

到目前为止,我的解决方案看起来像是命令式编程解决方案。

 let test seq =

    if Seq.forall(fun num -> num =1) then 1
    elif Seq.forall(fun num-> num = 2) then 2
    else None

3 个答案:

答案 0 :(得分:5)

您的解决方案很好!您不能使用模式匹配来很好地表达检查序列中的所有元素都具有某些值的功能-您必须使用when子句,但这与代码完全一样(但语法更长)。在这种情况下,使用if绝对没有错。

您可以通过定义自定义的活动模式来扩展模式匹配,这在此处为您提供了一个不错的选择。这是相当高级的F#,但是您可以定义一个自定义模式ForAll n,当输入是仅包含n值的序列时,该模式就会成功:

let (|ForAll|_|) n seq = 
  if Seq.forall (fun num -> num = n) seq then Some() else None

请注意,成功表示为Some,失败表示为None。现在,您可以使用模式匹配很好地解决您的问题:

let test = function
  | ForAll 1 -> Some 1
  | ForAll 2 -> Some 2
  | _ -> None

这看起来很不错,但是它依赖于更高级的功能-如果您需要在多个地方进行此操作,我会这样做。如果我只需要一个地方,就选择普通的if

答案 1 :(得分:3)

您可以使用带有保护子句的模式匹配来重写它:

let testList = [2;2;2]
let isOne x = x = 1
let isTwo x = x = 2

let forAll = function 
  | list when list |> List.forall isOne  -> Some 1
  | list when list |> List.forall isTwo  -> Some 2
  | _ -> None

let res = forAll testList //Some 2

答案 2 :(得分:3)

您可以在equals运算符上使用部分应用程序来代替该函数。

> let yes = [1;1;1];;
val yes : int list = [1; 1; 1]

> let no = [1;2;3];;
val no : int list = [1; 2; 3]

> yes |> List.forall ((=) 1);;
val it : bool = true

> no |> List.forall ((=) 1);;
val it : bool = false

这看起来更实用吗?而且我认为您应该在代码中返回Some 1,否则由于Option和int不是同一类型,您将得到类型错误。

如果您要检查所有元素是否相等(不仅仅是它们是否等于某个常数),可以执行以下操作:

> [1;2] |> List.pairwise |> List.forall (fun (a,b) -> a = b)
;;
val it : bool = false

> [1;1;1] |> List.pairwise |> List.forall (fun (a,b) -> a = b)
;;
val it : bool = true

在那里您将列表分为多个元组,并检查元组是否相等。这意味着所有元素都相等。