Scala将IndexedSeq [AnyVal]转换为Array [Int]

时间:2017-05-19 08:12:39

标签: arrays scala

我尝试使用Scala解决Codility的GenomicRangeQuery,为此我编写了以下函数:

def solution(s: String, p: Array[Int], q: Array[Int]): Array[Int] = {
  for (i <- p.indices) yield {
    val gen = s.substring(p(i), q(i) + 1)
    if (gen.contains('A')) 1
    else if (gen.contains('C')) 2
    else if (gen.contains('G')) 3
    else if (gen.contains('T')) 4
  }
}

我还没有做过很多测试,但它似乎解决了这个问题。

我的问题是for comprehension返回scala.collection.immutable.IndexedSeq[AnyVal],而该函数必须返回Array[Int],因此它会抛出type mismatch error

有没有办法让for comprehension返回一个Array [Int]或将IndexedSeq[AnyVal]转换为Array[Int]

3 个答案:

答案 0 :(得分:2)

def solution(s: String, p: Array[Int], q: Array[Int]): Array[Int] = {
  (for (i <- p.indices) yield {
    val gen = s.substring(p(i), q(i) + 1)
    if (gen.contains('A')) 1
    else if (gen.contains('C')) 2
    else if (gen.contains('G')) 3
    else 4
  }).toArray
}

if语句的问题在于没有默认值,这就是为什么你得到一个Any的IndexedSeq而不是Int。

答案 1 :(得分:2)

这里有两个问题,第一个来自p.indices,它返回scala.collection.immutable.Range而不是Array。做p.indices.toArray(或者像@sheunis建议的那样最后添加.toArray)解决了这个问题。

另一个问题来自你的if语句不完整,如果所有条件都为假,你的方法返回(): Unit(由编译器添加)。添加默认情况(例如else -1作为最后一个语句)应该可以解决第二个问题。

编辑:如果默认情况永远不会附加,您可以抛出异常,如下所示:

else {
  val err = "the input String can only contain the characters ACGT"
  throw new IllegalArgumentException(err)
}

这会告诉下一个程序员和编译器你的代码中发生了什么。请注意,throw表达式的类型为Nothing,因此在计算(Int, Int, Int, Nothing)的最小上限时,正确生成Int,与(Int, Int, Int, Unit)不同的是{ AnyVal

答案 2 :(得分:2)

sheunis'上面的答案主要涵盖了它。

您可以通过调用IndexedSeqArray强制转换为toArray,这样第一位非常简单。对于第二部分,因为您可以在所有if... else...个案例中删除可能的逻辑分支,所以yield可能会返回IntUnit类型,最近的共同祖先是AnyVal

请注意,如果您使用模式匹配替换了if... else...,那么您将明确地收到编译器警告,因为您没有捕获所有可能的case

gen match { case _ if gen.contains("A") => 1 case _ if gen.contains("C") => 2 ... // Throws warning unless you include a `case _ =>` with no `if` clause }