在Scala中,有没有一种简洁的方法来比较一个值和多个值

a14dhokn  于 2023-05-29  发布在  Scala
关注(0)|答案(8)|浏览(636)

假设我有一个变量x,我想检查它是否等于多个值a,b,c,d,e中的任何一个(我指的是==相等,而不是恒等式)。
在SQL查询中,使用

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

Scala中有没有类似的东西可以这么简单呢?我知道可以用一个复杂的表达式在一行中完成,比如构建一个HashSet并检查集合中是否存在,但是如果可以的话,我更喜欢使用一个简单的结构。

iibxawm4

iibxawm41#

您可以按如下方式实现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
wnvonmuf

wnvonmuf2#

我更喜欢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:以下是SeqLikecontains的定义:

def contains(elem: Any): Boolean = exists (_ == elem)
wixjitnu

wixjitnu3#

假设一个Set[A]也是一个A => Boolean,你可以说:

Set(a, b, c, d, e) apply x

实际上,为这个定义一些pimpin' sugar是很好的:

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)
6mzjoqzu

6mzjoqzu4#

通过综合所有其他答案,我得出了“正确”答案:

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

再见

gudnpqoy

gudnpqoy5#

存在:

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这样的盒装值,而不适用于区分身份和平等的类。为了证明这一点,我写了一个小类,证明错了::)

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)

这是最简单的答案。

myzjeezk

myzjeezk6#

Set(a, b, c, d, e)(x)也可以工作。我将把原因留给读者作为练习。:—)

wgeznvg7

wgeznvg77#

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

frebpwbc8#

也适用于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更新其他解决方案之一的请求被拒绝。)

相关问题