如何改造getPrime()方法使其仅返回质数且无需使用collect
解决Scala中getPrime()方法的改造问题
嘿,这问题很常见——你现在的getPrime方法返回的是混合了Int和Unit的序列,所以才需要用collect来过滤出质数。咱们直接把过滤逻辑整合到getPrime里面,让它直接返回纯质数的集合就好啦!
问题根源分析
先看你原来的getPrime代码:
def getPrime(range : Int) = { Range(2,range).map(x => if(isPrime(x)) x); }
这里用map的时候,当isPrime(x)为false时,if表达式没有else分支,Scala会默认返回Unit(也就是())。所以这个方法返回的是IndexedSeq[Any],里面既有质数(Int类型),又有无效的Unit值,这就是为什么调用时必须用collect来提取Int的原因。
改造方案
我们有两种简洁的方式来改造getPrime,让它直接返回纯质数序列:
方案1:使用filter(最直观)
直接过滤出满足isPrime条件的元素,返回的序列类型就是IndexedSeq[Int],完全不需要后续的collect:
def getPrime(range: Int) = { Range(2, range).filter(isPrime) }
方案2:使用collect(内部整合过滤逻辑)
如果更习惯用模式匹配的写法,也可以把collect放到方法内部,只保留符合条件的Int值:
def getPrime(range: Int) = { Range(2, range).collect { case x if isPrime(x) => x } }
改造后的主方法
现在getPrime(100)直接返回纯质数的序列,主方法可以简化成直接遍历打印:
def main(args: Array[String]) { getPrime(100).foreach(println) }
额外小优化(可选)
你的isPrime方法已经挺不错了,不过可以把Math.sqrt(no).toInt的计算缓存一下,避免重复计算:
def isPrime(no: Int): Boolean = { val sqrtNo = Math.sqrt(no).toInt !Range(2, sqrtNo + 1).exists(x => no % x == 0) }
这样改造之后,调用getPrime(100)就会直接返回100以内的所有质数,再也不用额外调用collect啦!
内容的提问来源于stack exchange,提问作者Navin Gelot
相关产品推荐
相关产品推荐

