我有两个列表,val aList = List(2,3,5,15,20)
和val bList = List (3,5,6)
。
我需要什么:
如果aList
中的元素大于10 ,则在结果中包含该元素。
否则,如果它出现在bList
中,则包含元素的平方。
所以,上面例子的答案是List(15,20,9,25)
。结果列表可以是任何顺序。
理解是最有效的方法吗?是否有可能在单一的理解 - 收益中实现这一目标?
答案 0 :(得分:5)
可能是这样的:
aList.flatMap { a =>
if (a > 10) Option(a) else bList.find(_ == a).map(a => a * a)
}
我们避免不必要的遍历bList
。
答案 1 :(得分:3)
我是在一次遍历中完成的,为此你不需要for yield
,那是flatMap
语法糖,但是你'不要在这里映射任何东西。
val res = aList.foldLeft(List.empty[Int]) { (acc, el) =>
if (el > 10) {
el :: acc
} else if (bList.contains(el)) {
(el * el) :: acc
} else {
acc
}
}
如果你想让这个稍微漂亮一点,可能会有所偏好,因为有些人可能不会选择写一个if case语句与宗教相符:
val res = aList.foldLeft(List.empty[Int]) { (acc, el) => el match {
case e if e > 10 => el :: acc
case e if bList.contains(e) => (e * e) :: acc
case _ => acc
}
}
此大O将为O(nlogm)
,其中n
的大小为aList
,m
的大小为bList
。在实践中它会好一点,因为你避免对每个大于10的元素进行对数时间查找。除非我的早晨咖啡还没有生效,否则我会错过。
答案 2 :(得分:2)
尝试类似的事情,
aList.filter(_>10) ++ bList.filter(aList.contains(_)).map(x => x*x)
或者避免bList中的元素超过10个(如果有的话),
aList.filter(_>10) ++ bList.filter(i => i<=10 && aList.contains(i)).map(x => x*x)
答案 3 :(得分:1)
我认为这里不需要for-comprehension
。此外,没有简单的方法可以使用for-compreshension
来完成此任务。
val aList = List(2,3,5,15,20)
val bList = List(3,5)
你可以这样做(转换为Set不会保证oder保存并可能导致任意顺序),
val commonEligibleInts = (aList.filter(i => i <= 10).toSet & bList.toSet).toList
val result = aList.filter(i => i > 10) ++ commonEligibleInts.map(i => i * i)
// result: List[Int] = List(15, 20, 9, 25)
您可以使用以下for-comprehension
,但这不会为您提供所需的排序(此处的订单将与aList
中的订单相同),
val bListSet = bList.toSet
val result2 = for {
i <- aList
r <- if (i > 10) Some(i) else if (bListSet.contains(i)) Some(i*i) else None
} yield r
// result2: List[Int] = List(9, 25, 15, 20)
或者,您可以采用这种方法,这种方法比上述方法更有效,并且还会导致所需的排序,
val bListSet = bList.toSet
val result3 = aList.flatMap({
case i if i > 10 => Some(i)
case i if bListSet.contains(i) => Some(i*i)
case _ => None
})
// result3: List[Int] = List(15, 20, 9, 25)
答案 4 :(得分:1)
我为猫皮肤的替代方案
val (x,y) = aList.partition( _ >10)
val r = x++(y intersect bList).map(e=>e*e)
// List(15, 20, 9, 25)