Scala 序列 groupBy 然后将不同的函数映射到组然后将其展平
Scala sequence groupBy then map different functions to groups then flatten it
通常我有这样的元素列表
List(A1, A2, B1, A3, B2, B3, B4, A4, ...)
所有元素都可以分为两组:
A
组
B
组
我想为每个组应用不同的功能:
- 对于
A
:myFunc1
- 对于
B
:myFunc2
然后将部分列表汇总到一个列表中。
我通过这段代码获得:
myList
.groupBy(p => p.sourceId < 0 && p.signerId.isEmpty)
.flatMap(tuple => tuple match {
case tre if tuple._1 =>
tuple
._2
.map(myFunc1)
case fls @ _ =>
tuple
._2
.map(myFunc2)
})
但是这段代码看起来很难看,因为每次我需要从 Map
中获取任何键 (true
/false
) 的 tuple._2
之类的值,我从groupBy
。
完成这项工作的好方法是什么?将序列分成 2 组 + 为它映射不同的函数 + 将组展平到列表中?
答案的一些变体
使用 map
+ if/else
:
myList.map(p =>
if (p.sourceId < 0 && p.signerId.isEmpty)
myFunc1(p)
else
myFunc2(p)
)
类似于但使用match/case
代替if/else
:
vkPosts.map({
case p1 if p.sourceId < 0 && p.signerId.isEmpty => myFun1(p1)
case pN if p.sourceId > 0 => myFunN(pN)
case pUndefined @ _ => myFun2(pUndefined)
})
在这种情况下,您实际上不需要分组,您可以只使用一个包含 if 语句的映射。像
myList.map(p =>
if (p.sourceId < 0 && p.signerId.isEmpty)
myFunc1(p)
else
myFunc2(p)
)
在其他情况下,您可能希望将集合一分为二。有一个 partition
函数。你可以这样做
val (type1, type2) = myList.partition(p => p.sourceId < 0 && p.signerId.isEmpty)
type1.foreach(p => s"Type 1: $p")
type2.foreach(p => s"Type 2: $p")
如果您需要将所有 myFunc1()
个结果组合在一起并与 myFunc2()
个结果分开。
val (a,b) = myList.partition(p => p.sourceId < 0 && p.signerId.isEmpty)
val rslt = a.map(myFunc1) ++ b.map(myFunc2) //or something like this
如果您使用的是 Scala 2。13.x 您可以 pipe
将它们放在一起。
import scala.util.chaining._
myList.partition(p => p.sourceId < 0 && p.signerId.isEmpty)
.pipe(t => t._1.map(myFunc1) ++ t._2.map(myFunc2))
通常我有这样的元素列表
List(A1, A2, B1, A3, B2, B3, B4, A4, ...)
所有元素都可以分为两组:
A
组B
组
我想为每个组应用不同的功能:
- 对于
A
:myFunc1
- 对于
B
:myFunc2
然后将部分列表汇总到一个列表中。
我通过这段代码获得:
myList
.groupBy(p => p.sourceId < 0 && p.signerId.isEmpty)
.flatMap(tuple => tuple match {
case tre if tuple._1 =>
tuple
._2
.map(myFunc1)
case fls @ _ =>
tuple
._2
.map(myFunc2)
})
但是这段代码看起来很难看,因为每次我需要从 Map
中获取任何键 (true
/false
) 的 tuple._2
之类的值,我从groupBy
。
完成这项工作的好方法是什么?将序列分成 2 组 + 为它映射不同的函数 + 将组展平到列表中?
答案的一些变体
map
+ if/else
:
myList.map(p =>
if (p.sourceId < 0 && p.signerId.isEmpty)
myFunc1(p)
else
myFunc2(p)
)
类似于match/case
代替if/else
:
vkPosts.map({
case p1 if p.sourceId < 0 && p.signerId.isEmpty => myFun1(p1)
case pN if p.sourceId > 0 => myFunN(pN)
case pUndefined @ _ => myFun2(pUndefined)
})
在这种情况下,您实际上不需要分组,您可以只使用一个包含 if 语句的映射。像
myList.map(p =>
if (p.sourceId < 0 && p.signerId.isEmpty)
myFunc1(p)
else
myFunc2(p)
)
在其他情况下,您可能希望将集合一分为二。有一个 partition
函数。你可以这样做
val (type1, type2) = myList.partition(p => p.sourceId < 0 && p.signerId.isEmpty)
type1.foreach(p => s"Type 1: $p")
type2.foreach(p => s"Type 2: $p")
如果您需要将所有 myFunc1()
个结果组合在一起并与 myFunc2()
个结果分开。
val (a,b) = myList.partition(p => p.sourceId < 0 && p.signerId.isEmpty)
val rslt = a.map(myFunc1) ++ b.map(myFunc2) //or something like this
如果您使用的是 Scala 2。13.x 您可以 pipe
将它们放在一起。
import scala.util.chaining._
myList.partition(p => p.sourceId < 0 && p.signerId.isEmpty)
.pipe(t => t._1.map(myFunc1) ++ t._2.map(myFunc2))