В Scala есть удобный и простой способ сравнить одно значение с несколькими - PullRequest
17 голосов
/ 08 мая 2011

Допустим, у меня есть переменная x, и я хочу проверить, равно ли она какому-либо из нескольких значений a, b, c, d, e (я имею в виду равенство ==, а не тождество).

В запросе SQL та же концепция обрабатывается с помощью

WHERE x IN (a, b, c, d, e).

Есть ли в Scala что-то такое же простое, как это? Я знаю, что в противном случае можно сделать это в одной строке со сложным выражением, таким как создание HashSet и проверка существования в наборе, но я бы предпочел использовать простую конструкцию, если она доступна.

Ответы [ 7 ]

24 голосов
/ 08 мая 2011

Вы можете реализовать оператор 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
22 голосов
/ 08 мая 2011

Я бы предпочел 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)
12 голосов
/ 08 мая 2011

Учитывая, что 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)
9 голосов
/ 08 мая 2011

Синтезируя все остальные ответы, я придумал правильный ответ:

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 голосов
/ 08 мая 2011

существует:

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

- это самый простой ответ.

4 голосов
/ 09 мая 2011

Set(a, b, c, d, e)(x) тоже работает. Я оставлю причины для этого в качестве упражнения для читателя. : -)

0 голосов
/ 08 мая 2017
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)
...