【发布时间】:2011-05-08 13:06:42
【问题描述】:
假设我有一个变量 x,我想检查它是否等于多个值 a、b、c、d、e 中的任何一个(我的意思是 == 相等,而不是标识)。
在 SQL 查询中处理相同的概念
WHERE x IN (a, b, c, d, e).
Scala 中是否有类似的东西这么简单?我知道可以用复杂的表达式在一行中完成它,例如构建一个 HashSet 并检查集合中是否存在,但如果它可用,我更喜欢使用一个简单的构造。
【问题讨论】:
假设我有一个变量 x,我想检查它是否等于多个值 a、b、c、d、e 中的任何一个(我的意思是 == 相等,而不是标识)。
在 SQL 查询中处理相同的概念
WHERE x IN (a, b, c, d, e).
Scala 中是否有类似的东西这么简单?我知道可以用复杂的表达式在一行中完成它,例如构建一个 HashSet 并检查集合中是否存在,但如果它可用,我更喜欢使用一个简单的构造。
【问题讨论】:
您可以按如下方式实现in 运算符:
scala> implicit def anyWithIn[A](a: A) = new {
| def in(as: A*) = as.exists(_ == a)
| }
anyWithIn: [A](a: A)java.lang.Object{def in(as: A*): Boolean}
scala> 5 in (3, 4, 9, 11)
res0: Boolean = false
scala> 5 in (3, 4, 9, 11, 5)
res1: Boolean = true
【讨论】:
A => Boolean,这样你就可以写 5 ∈: Set(1, 2, 3, 4, 5)
【讨论】:
contains 只适用于身份,而不是平等。我投了你的票,并开始在我的答案中写一个更长的证明,但我证明自己错了。对不起。 :)
contains(a) 只是exists(_ == a) 的糖,所以我们的答案是等价的。
鉴于Set[A] 也是A => Boolean,您可以说:
Set(a, b, c, d, e) apply x
为此定义一些 pimpin' 糖实际上非常好:
class PredicateW[A](self : A => Boolean) {
def ∈:(a : A) = self apply a
}
implicit def pred2wrapper[A](p : A => Boolean) = new PredicateW(p)
然后你可以这样写代码:
x ∈: Set(a, b, c, d, e)
【讨论】:
通过综合所有其他答案,我想出了正确答案:
implicit def anyWithIn[A](a: A) = new {
def ∈(as: A*) = as.contains(a)
}
anyWithIn: [A](a: A)java.lang.Object{def ?(as: A*): Boolean}
5 ∈ (1,3,5)
res1: Boolean = true
塔达。
【讨论】:
存在:
List (3, 4, 5).exists (_ == 4)
// res20: Boolean = true
查找和过滤接近:
List (3, 4, 5).find (_ == 4)
// res16: Option[Int] = Some(4)
List (3, 4, 5).filter (_ == 4)
// res17: List[Int] = List(4)
与其他答案一样,我的第一个答案是使用包含:
List (3, 4, 5).contains (4)
但后来我想,它只适用于像 4 这样的盒装值,而不适用于区分身份和平等的类。为了证明这一点,我写了一个小班,证明我错了::)
class Ue (val i: Int) {
override def equals (other: Any) = other match {
case o: Ue => i == o.i
case _ => false }
}
val a = new Ue (4)
// a: Ue = Ue@1e040e5
val b = new Ue (4)
// b: Ue = Ue@1a4548b (no identity)
a == b
// res110: Boolean = true (surprise?)
a.equals (b)
// res112: Boolean = true (expected)
a.eq (b)
// res113: Boolean = false (expected)
List (a).contains (b)
// res119: Boolean = true (surprise)
List (a).exists (_ == b)
// res120: Boolean = true (expected)
List (a).exists (_ .eq (b))
// res121: Boolean = false (expected)
我明白了,我必须更频繁地使用 equals/eq/== 才能将区别输入我的大脑。
List (3, 4, 5).contains (4)
恕我直言,这是最简单的答案。
【讨论】:
Set(a, b, c, d, e)(x) 也可以。我将把它的原因留给读者作为练习。 :-)
【讨论】:
class Ue (val i: Int) {
override def equals (other: Any) = other match {
case o: Ue => i == o.i
case _ => false }
}
val a = new Ue (4)
// a: Ue = Ue@1e040e5
val b = new Ue (4)
// b: Ue = Ue@1a4548b (no identity)
a == b
// res110: Boolean = true (surprise?)
a.equals (b)
// res112: Boolean = true (expected)
a.eq (b)
// res113: Boolean = false (expected)
List (a).contains (b)
// res119: Boolean = true (surprise)
List (a).exists (_ == b)
// res120: Boolean = true (expected)
List (a).exists (_ .eq (b))
// res121: Boolean = false (expected)
【讨论】: