【问题标题】:In Scala, is there a neat and simple way to compare one value with multiple values在 Scala 中,是否有一种简洁的方法可以将一个值与多个值进行比较
【发布时间】:2011-05-08 13:06:42
【问题描述】:

假设我有一个变量 x,我想检查它是否等于多个值 a、b、c、d、e 中的任何一个(我的意思是 == 相等,而不是标识)。

在 SQL 查询中处理相同的概念

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

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

【问题讨论】:

    标签: scala equality


    【解决方案1】:

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

    【讨论】:

    • 太棒了。直接进入我自己的一组标准扩展,这些扩展最终出现在我的所有项目中,并且可以说值得标准库包含
    • 查看我的答案,了解如何以 other 方式执行此操作:即拉个 A => Boolean,这样你就可以写 5 ∈: Set(1, 2, 3, 4, 5)
    • 整洁!这应该内置在 Scala 的下一个版本中。但事实上,它需要在任何需要的地方显式导入或继承隐式转换,所以现在我将使用 List/contains 技术。
    【解决方案2】:

    比起exists(_ == a),我更喜欢contains(a)

    scala> List(3, 4, 5) contains 4
    res0: Boolean = true
    
    scala> List(3, 4, 5) contains 6
    res1: Boolean = false
    

    更新:contains 定义在 SeqLike 中,因此上述内容适用于任何序列。

    更新2:这是containsSeqLike中的定义:

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

    【讨论】:

    • 对不起,我投了你的票,因为我认为contains 只适用于身份,而不是平等。我投了你的票,并开始在我的答案中写一个更长的证明,但我证明自己错了。对不起。 :)
    • @user 我对你的答案投了赞成票,因为正如你在我的第二次更新中看到的那样,contains(a) 只是exists(_ == a) 的糖,所以我们的答案是等价的。
    • 这可能只是糖,但我是一个甜蜜的人,既然你编辑了你的答案,我可以更正我的投票。 (Scala 只是 Java 的语法糖,它是汇编程序的语法糖……)。
    【解决方案3】:

    鉴于Set[A] 也是A => Boolean,您可以说:

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

    为此定义一些 pimpin' 糖实际上非常好:

    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
    

    塔达。

    【讨论】:

    • 嘿,我会捍卫它比迄今为止给出的任何其他答案都明显更好(比missingfaktor的解决方案更易读,比Oxbow_lakes的更容易理解,更易于理解和Dan的......)
    【解决方案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 这样的盒装值,而不适用于区分身份和平等的类。为了证明这一点,我写了一个小班,证明错了::)

    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)
    

    恕我直言,这是最简单的答案。

    【讨论】:

      【解决方案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 = 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)
        

        【讨论】:

          猜你喜欢
          • 2012-11-24
          • 1970-01-01
          • 1970-01-01
          • 2018-08-29
          • 1970-01-01
          • 2020-04-26
          • 1970-01-01
          • 2021-12-12
          相关资源
          最近更新 更多