【发布时间】:2017-10-27 08:01:38
【问题描述】:
我是 Scala 的新手,我知道必须有一个很好的方法来做到这一点,但我无法想出一些好的和可读的东西。
我有一组 id(字符串),对于每个 id,我运行一些返回布尔值的函数。
结果是一个Set[Boolean],但我想创建一个包含两个数字的元组,一个是真数,一个是假数。
什么是干净/可读的方式来做到这一点?
【问题讨论】:
我是 Scala 的新手,我知道必须有一个很好的方法来做到这一点,但我无法想出一些好的和可读的东西。
我有一组 id(字符串),对于每个 id,我运行一些返回布尔值的函数。
结果是一个Set[Boolean],但我想创建一个包含两个数字的元组,一个是真数,一个是假数。
什么是干净/可读的方式来做到这一点?
【问题讨论】:
鉴于您的ids 和f:
val ids: Set[String] = ???
def f(s: String): Boolean = ???
以下内容使用内置的partition 函数相当简洁:
val (trues, falses) = ids partition f
(trues.size, falses.size)
【讨论】:
您可以使用Seq 的count 方法:
val ids: Seq[String] = Seq("1", "12", "3")
def containsOne(s: String) = s.contains('1')
val processedIds = ids.map(containsOne)
// first item is amount of trues, second is amount of falses
val count: (Int, Int) = (processedIds.count(identity), processedIds.count(_ == false))
您必须使用Seq,因为Set 将“展平”Boolean 的集合(最大为 2,不允许重复)。
【讨论】:
这是一个计算集合中偶数和奇数个数的表达式:
Set(3,4,5,6,8,3).toSeq.map{_ % 2 == 0}
.foldLeft((0,0)){(t,c) => if (c) (t._1+1, t._2) else (t._1, t._2+1)}
toSeq 是防止map 的输出只是Set 所必需的。
只需将{_ % 2 == 0} 替换为对您的函数的调用即可。
【讨论】:
鉴于你的 fn,
scala> def fn(x: String) = x.contains("customer")
fn: (x: String)Boolean
你必须.map创建boolean -> Set(Id),然后按布尔值聚合,然后计算每个布尔值有多少个ID
scala> Set("customerId-1", "customerId-2", "id-3", "id-4")
.map(x => fn(x) -> x)
.groupBy(_._1)
.map { case (boolean, set) => boolean -> set.size }
res51: scala.collection.immutable.Map[Boolean,Int] = Map(false -> 2, true -> 2)
【讨论】:
这是我对单行的尝试(除了它不适合这个小盒子的一行:(
如果除以 3 余数为 1,则我的测试函数为真,否则为假,并且我在 1 到 6 的范围内运行它(即 1,2,3,4,5):
scala> val x = (1 to 6).partition(_%3 == 1) match
| { case (s1,s2) => (s1.length, s2.length) }
x: (Int, Int) = (2,4)
所以,把 main 函数写得更笼统一些,
scala> def boolCounter[T](
| s: Seq[T],
| f: T => Boolean): (Integer, Integer) =
| s.partition(f) match { case (s1, s2) => (s1.length, s2.length) }
boolCounter: [T](s: Seq[T], f: T => Boolean)(Integer, Integer)
scala> val r = 1 to 6
r: scala.collection.immutable.Range.Inclusive = Range 1 to 6
scala> val f: Int => Boolean = { x => x%3 == 1}
f: Int => Boolean = $$Lambda$1252/1891031939@5a090f62
scala> boolCounter(r, f)
res0: (Integer, Integer) = (2,4)
【讨论】: