有没有办法在线进行多值比较?

时间:2012-07-13 19:51:12

标签: f# comparison

我甚至对这个问题感到愚蠢,因为它看起来很琐碎,但是我的大脑让我失望了。如果我有以下内容:

let a, b, c = 1, 1, 1

是否有一种方法可以确定a,b和c是否都保持相同的值。类似的东西:

let result = (a = b = c)

这失败是因为表达式a = b返回true而下一个表达式导致true = c并抱怨它期望int,而不是bool。我唯一能想到的是:

a = b && a = c && b = c

当我想添加更多变量时,它将无效。

我真正想做的是:

let same (x: string * string * string) =
    match x with
    | (a, a, a) -> true
    | _ -> false

我希望我可以将所有元素匹配到一个元素中,如果它们不同,它会继续前进,但它会在匹配中的第二个元素上说它已被绑定。

4 个答案:

答案 0 :(得分:8)

检查列表中的每个值是否相同:

let rec same = function
  | x::y::_ when x <> y -> false
  | _::xs -> same xs
  | [] -> true

用法

let a, b, c = 1, 1, 1
same [a; b; c] //true

答案 1 :(得分:2)

let same (a, b, c) = a = b && b = c

答案 2 :(得分:2)

我会尝试使用forall函数来确定所有数字是否相同。

let list = [a; b; c;];;
List.forall (fun n -> n = a) list;;
val it : bool = true

答案 3 :(得分:2)

此解决方案可生成所需的语法。令我惊讶的是,相当快。此外,似乎是使用monad的一个很好的例子,也称为Computation Expressions

// Generic
let inline mOp1<'a> op sample x = op sample x, sample
let inline mOp2<'a> op1 op2 (b, sample) x = op1 b (op2 sample x), sample

// Implementation for (=) and (&&)
let (==) = mOp1 (=)
let (&=) = mOp2 (&&) (=)

// Use
let ret1 = a == b &= c &= d &= e |> fst

如何运作

该方法是一个非常简化的 State monad 。 monadic类型是(bool, 'T)的元组。第一个组件是正在进行的计算的布尔值,第二个组件是要与之比较的样本值。

(==)会初始化monad,类似于Delay运算符 (&=)用于所有后续比较。它类似于Bind运算符 我们不需要Return,因为fst会很好用。{ mOp1mOp2是逻辑运算的抽象。这些允许定义自己的运算符。以下是or-equaland-greater-than的示例:

let (|=) = mOp2 (||) (=)
let (.>) = mOp1 (>)
let (&>) = mOp2 (&&) (>)
// Use
let ret2 = a == b |= c |= d |= e |> fst // if any of b,c,d,e equals to a
let ret3 = 5 .> 3 &> 4 |> fst // true: 5>3 && 5>4
let ret4 = 5 .> 3 &> 8 &> 4 |> fst // false

性能

我非常喜欢@ildjarn的漂亮解决方案,但构建List的速度非常慢,所以我的主要目标是表现。
运行8个比较链,1000万次:

  • 04972ms a=b && a=с && ...
  • 23138ms List - 基于
  • 12367ms monadic