Reputation: 2055
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.
Upvotes: 18
Views: 16283
Reputation: 2121
Solution which also works with Scala 3:
implicit class PowerAny[A](a: A) {
/**
* 2 in (1,2,3,"foo") -> true
*
* 4 in (1,2,3,"foo") -> false
*/
def in(seq: A*): Boolean = seq.contains(a)
}
(My request to update one of the other solutions was rejected.)
Upvotes: 0
Reputation: 1
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)
Upvotes: 0
Reputation: 4785
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)
Upvotes: 22
Reputation: 36260
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.
Upvotes: 5
Reputation: 297265
Set(a, b, c, d, e)(x)
works as well. I'll leave the reasons for it as an exercise to the reader. :-)
Upvotes: 4
Reputation: 44416
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.
Upvotes: 11
Reputation: 134310
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)
Upvotes: 12
Reputation: 92076
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
Upvotes: 24