【问题标题】:Finding an item that matches predicate in Scala在 Scala 中查找与谓词匹配的项目
【发布时间】:2012-03-22 07:56:01
【问题描述】:

我正在尝试在 scala 集合中搜索列表中与某个谓词匹配的项目。我不一定需要返回值,只是测试列表是否包含它。

在 Java 中,我可能会这样做:

for ( Object item : collection ) {
    if ( condition1(item) && condition2(item) ) {
       return true;
    }
}
return false;

在 Groovy 中,我可以执行以下操作:

return collection.find { condition1(it) && condition2(it) } != null

在 Scala 中执行此操作的惯用方式是什么?我当然可以将 Java 循环样式转换为 Scala,但我觉得有一种更实用的方法可以做到这一点。

【问题讨论】:

  • 我不会太担心惯用性或功能性:Scala 库中的集合具有 existsfind 方法(区别在于 find 返回元素)返回为一旦找到元素。两者都是用varwhile 循环实现的,看起来与你的java 实现非常相似(除了将谓词作为参数)。

标签: scala collections idioms


【解决方案1】:

过滤并存在关键字以从列表中获取匹配值

val values = List(1,2,3,4,5,6,7,8,9,10,....,1000) //List -1
val factors= List(5,7) // List -2

//To get the factors of List-2 from List-1
values .filter(a => factors.exists(b => a%b == 0)) //Apply different logic for our convenience

给定的代码有助于从 2 个不同的列表中获取匹配值

【讨论】:

    【解决方案2】:

    scala 的方式是使用exists:

    collection.exists(item => condition1(item) && condition2(item))
    

    从 java 8 开始你可以使用anyMatch:

    collection.stream().anyMatch(item -> condition1(item) && condition2(item));
    

    这比普通的 for 或 foreach 要好得多。

    【讨论】:

      【解决方案3】:

      测试值匹配谓词是否存在

      如果您只是对测试某个值是否存在感兴趣,您可以使用....exists

      scala> val l=(1 to 4) toList
      l: List[Int] = List(1, 2, 3, 4)
      
      scala> l exists (_>5)
      res1: Boolean = false
      
      scala> l exists (_<2)
      res2: Boolean = true
      
      scala> l exists (a => a<2 || a>5)
      res3: Boolean = true
      

      其他方法(一些基于cmets):

      计算匹配元素

      计算满足谓词的元素(并检查 count 是否 > 0)

      scala> (l count (_ < 3)) > 0
      res4: Boolean = true
      

      返回第一个匹配元素

      找到满足谓词的第一个元素(根据 Tomer Gabel 和 Luigi Plinge 的建议,这应该更有效,因为它会在找到一个满足谓词的元素时立即返回,而不是遍历整个 List)

      scala> l find (_ < 3)
      res5: Option[Int] = Some(1) 
      
      // also see if we found some element by
      // checking if the returned Option has a value in it
      scala> l.find(_ < 3) isDefined
      res6: Boolean = true
      

      测试是否存在精确值

      对于我们实际上只检查一个特定元素是否在列表中的简单情况

      scala> l contains 2
      res7: Boolean = true
      

      【讨论】:

      • 如果您对返回值感兴趣,请使用 findFirst。您还可以使用自命名函数获取计数。都采用相同的谓词。
      • find,不是findFirst,但是是的,这比过滤整个列表更有效
      • @LuigiPlinge 我在您的更正中添加了 Tomer 的建议。谢谢!
      【解决方案4】:

      使用过滤器:

      scala> val collection = List(1,2,3,4,5)
      collection: List[Int] = List(1, 2, 3, 4, 5)
      
      // take only that values that both are even and greater than 3 
      scala> collection.filter(x => (x % 2 == 0) && (x > 3))
      res1: List[Int] = List(4)
      
      // you can return this in order to check that there such values
      scala> res1.isEmpty
      res2: Boolean = false
      
      // now query for elements that definitely not in collection
      scala> collection.filter(x => (x % 2 == 0) && (x > 5))
      res3: List[Int] = List()
      
      scala> res3.isEmpty
      res4: Boolean = true
      

      但如果你只需要检查使用exists:

      scala> collection.exists( x => x % 2 == 0 )
      res6: Boolean = true
      

      【讨论】:

      • 是的,这看起来就像我正在寻找的方法。还在学习 Scala...谢谢。
      • 简单一点collection exists { x =&gt; condition1(x) &amp;&amp; condition2(x) }
      • @是的,我也加了这个
      • @om-nom-nom,是的,非常同步:)
      • @Stas 是的,它 exist 在第一次出现 true 时退出(双关语)
      猜你喜欢
      • 1970-01-01
      • 2018-01-24
      • 1970-01-01
      • 1970-01-01
      • 2016-07-04
      • 2012-01-21
      • 2018-12-03
      • 1970-01-01
      相关资源
      最近更新 更多