Scala convert IndexedSeq [AnyVal] to Array [Int]

I am trying to solve Codility GenomicRangeQuery using Scala and for this purpose I wrote the following function:

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
  }
}

      

I haven't tested much, but it seems to have solved the problem.

My problem is that, to understand, returns scala.collection.immutable.IndexedSeq[AnyVal]

, and the function has to return Array[Int]

and therefore throw type mismatch error

.

Is there a way to make it return Array [Int], or convert IndexedSeq[AnyVal]

to Array[Int]

?

+3


source to share


3 answers


Sheunis' answer above mostly covers it.

You can force IndexedSeq

to Array

a call toArray

to the first bit it was pretty simple. For the second part, since there is a possible logical branch where you can go through all of your cases if... else...

, it is possible that yours yield

should return types Int

and Unit

whose closest common ancestor is AnyVal

.



Note that if you replace yours if... else...

with pattern matching, you will explicitly get a compiler warning because you won't catch all the possible ones 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 }

+2


source


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
}

      



The problem with the if statement is that there is no default value, so you get IndexedSeq from Any and not Int.

+2


source


There are two problems here, the first one p.indices

, which returns scala.collection.immutable.Range

instead Array

. Doing it p.indices.toArray

(or adding .toArray

at the end as @sheunis suggested) fixes the problem.

Another problem comes from your if statement, which is incomplete, if all conditions are false, your method returns (): Unit

(which was added by the compiler). Adding a default case, for example else -1

as the last statement, should solve this second problem.

Edit . If the default case can never be added, you can make an exception like this:

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

      

This informs both the next programmer and the compiler about what's going on in your code. Note that expressions throw

are of type Nothing

, so when calculating the smallest upper bound, (Int, Int, Int, Nothing)

output correctly Int

, as opposed to (Int, Int, Int, Unit)

which is lubed before AnyVal

.

+2


source







All Articles