В Scala существует ли простой и простой способ сравнить одно значение с несколькими значениями
Скажем, у меня есть переменная x, и я хочу проверить, соответствует ли она одному из нескольких значений a, b, c, d, e (я имею в виду равенство ==, а не идентификатор).
В запросе SQL одна и та же концепция обрабатывается с помощью
WHERE x IN (a, b, c, d, e).
Есть ли что-то эквивалентное в Scala, что так же просто? Я знаю, что в противном случае это можно сделать в одной строке с таким сложным выражением, как построение HashSet и проверка наличия в наборе, но я бы предпочел использовать простую конструкцию, если она доступна.
Ответы
Ответ 1
Я бы предпочел contains(a)
над exists(_ == a)
:
scala> List(3, 4, 5) contains 4
res0: Boolean = true
scala> List(3, 4, 5) contains 6
res1: Boolean = false
Обновление: contains
определено в SeqLike
, поэтому вышеописанное работает с любой последовательностью.
Обновление 2: Ниже приведено определение contains
в SeqLike
:
def contains(elem: Any): Boolean = exists (_ == elem)
Ответ 2
Вы можете реализовать оператор 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
Ответ 3
Учитывая, что a Set[A]
также является A => Boolean
, вы можете просто сказать:
Set(a, b, c, d, e) apply x
На самом деле довольно неплохо определить какой-то пимпинский сахар для этого:
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)
Ответ 4
Синтезируя все остальные ответы, я придумал правильный ответ:
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
Та-да.
Ответ 5
существует:
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, а не для классов, которые различают идентичность и равенство. Чтобы доказать это, я написал небольшой класс, который оказался me неправильным::)
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 = [email protected]
val b = new Ue (4)
// b: Ue = [email protected] (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)
- это самый простой ответ.
Ответ 6
Set(a, b, c, d, e)(x)
работает. Я оставлю причины для этого как упражнение для читателя.: -)
Ответ 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 = [email protected]
val b = new Ue (4)
// b: Ue = [email protected] (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)