我有2个列表:lista
和listb
。对于lista
中的每个元素,我想检查每个元素的a_type
是否在b_type
的{{1}}中。如果listb
,请获取相应true
的{{1}}并构建对象b_name
。然后,我应该返回构造b_type
的列表。
有没有办法在Scala中执行此操作,最好没有任何可变集合?
objc
答案 0 :(得分:0)
列表中的查找需要在O(n)时间内遍历,这是低效的。因此,您要做的第一件事就是创建从b_type
到b_name
的地图:
val bTypeToBname = listb.map(b => (b.b_type, b_name)).toMap
然后,您遍历lista
,在地图中查找给定b_name
是否有相应的a.a_type
,并构建objc
:
val cs = for {
a <- lista
b_name <- bTypeToBname.get(a.a_type)
} yield objc(a.a_id, a.a_type, b_name)
注意Scala for-comprehensions如何自动过滤那些未定义bTypeToBname(a.a_type)
的情况:然后简单地跳过相应的a
。这是因为我们使用bTypeToBname.get(a.a_type)
(返回Option
),而不是直接调用bTypeToBname(a.a_type)
(这会导致NoSuchElementException
)。据我所知,这种过滤正是你想要的行为。
答案 1 :(得分:0)
case class A(aId: String, aType: String)
case class B(bId: String, bType: String, bName: String)
case class C(cId: String, cType: String, cName: String)
def getNames(aList: List[A], bList: List[B]): List[C] = {
val bMap: Map[String, B] = bList.map(b => b.bType -> b)(collection.breakOut)
aList.flatMap(a => bMap.get(a.aType).map(b => C(a.aId, a.aType, b.bName)))
}
答案 2 :(得分:0)
与安德烈的答案相同,但没有理解,所以你可以看到里面发生了什么。
// make listb into a map from type to name for efficiency
val bs = listb.map(b => b.b_type -> b_name).toMap
val listc: Seq[objc] = lista
.flatMap(a => // flatmap to exclude types not in listb
bs.get(a.a_type) // get an option from blist
.map(bName => objc(a.a_id, a.a_type, bName)) // if there is a b name for that type, make an objc
)