在 Scala 中查找与谓词匹配的项目

Posted

技术标签:

【中文标题】在 Scala 中查找与谓词匹配的项目【英文标题】:Finding an item that matches predicate in 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 实现非常相似(除了将谓词作为参数)。 【参考方案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 时退出(双关语)

以上是关于在 Scala 中查找与谓词匹配的项目的主要内容,如果未能解决你的问题,请参考以下文章

谓词匹配一对多关系核心数据

0 或多个项目的 LINQ Single() 异常

断言每个对象属性都匹配 kotlin 测试中的给定谓词

NHibernate 与 LINQ(谓词?)

核心数据谓词对多

NSPredicate 仅查找第一个匹配项