В 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)