问题
Say I have a variable x, and I want to check if it's equal to any one of multiple values a, b, c, d, e (I mean the == equality, not identity).
In an SQL query the same concept is handled with
WHERE x IN (a, b, c, d, e).
Is there something equivalent in Scala that's as straightforward as that? I know it's otherwise possible to do it in one line with a complex expression such as building a HashSet and checking for existence in the set, but I'd prefer to use a simple construct if it's available.
回答1:
I would prefer contains(a)
over exists(_ == a)
:
scala> List(3, 4, 5) contains 4
res0: Boolean = true
scala> List(3, 4, 5) contains 6
res1: Boolean = false
Update: contains
is defined in SeqLike, so the above works with any sequence.
Update 2: Here is the definition of contains in SeqLike
:
def contains(elem: Any): Boolean = exists (_ == elem)
回答2:
You could implement an in
operator as follows:
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
回答3:
Given that a Set[A]
is also a A => Boolean
, you can just say:
Set(a, b, c, d, e) apply x
It's actually quite nice to define some pimpin' sugar for this:
class PredicateW[A](self : A => Boolean) {
def ∈:(a : A) = self apply a
}
implicit def pred2wrapper[A](p : A => Boolean) = new PredicateW(p)
Then you can write the code like so:
x ∈: Set(a, b, c, d, e)
回答4:
By synthesizing all the other answers, I have come up with the correct answer:
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
Ta-da.
回答5:
exists:
List (3, 4, 5).exists (_ == 4)
// res20: Boolean = true
find and filter come close:
List (3, 4, 5).find (_ == 4)
// res16: Option[Int] = Some(4)
List (3, 4, 5).filter (_ == 4)
// res17: List[Int] = List(4)
My first answer was, as other answers, to use contain:
List (3, 4, 5).contains (4)
but then I thought, it would only work for boxed values like 4, not for classes, which distinguish identity and equality. To prove it, I wrote a small class, which proved me wrong: :)
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)
I see, I have to use equals/eq/== more often, to get the distinctions into my brain.
List (3, 4, 5).contains (4)
is imho the answer which is most easy.
回答6:
Set(a, b, c, d, e)(x)
works as well. I'll leave the reasons for it as an exercise to the reader. :-)
回答7:
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)
来源:https://stackoverflow.com/questions/5927608/in-scala-is-there-a-neat-and-simple-way-to-compare-one-value-with-multiple-valu