Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala convert IndexedSeq[AnyVal] to Array[Int]

Tags:

arrays

scala

I'm trying to solve Codility's GenomicRangeQuery using Scala and to that end 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 done a lot of testing but it seems to solve the problem.

My issue is the for comprehension returns an scala.collection.immutable.IndexedSeq[AnyVal], while the function must return an Array[Int] and therefore it's throwing a type mismatch error.

Is there any way to make the for comprehension return an Array[Int] or transform the IndexedSeq[AnyVal] into an Array[Int]?

like image 434
Micho Avatar asked May 19 '17 08:05

Micho


People also ask

What is indexedseq in Scala?

IndexedSeq is a trait. Per the Scaladoc, IndexedSeq is “a base trait for indexed sequences. Indexed sequences support constant-time or near constant-time element access and length computation.” In Scala 2.12.4 — which I use for all of the examples that follow — you’ll see that IndexedSeq is actually backed by Vector:

How to convert list to array in Scala?

In Scala we usually use Lists to store and manipulate data. But Arrays are also available—these are somewhat harder to work with. Here: We use toArray to convert the List to an Array. We print the values of the Array with a foreach call. List to string, StringBuilder.

What is implicit conversion from indexedseq to any2stringadd in Scala?

This implicitly inherited member is shadowed by one or more members in this class. This member is added by an implicit conversion from IndexedSeq [ A] to any2stringadd [ IndexedSeq [ A ]] performed by method any2stringadd in scala.Predef. Returns string formatted according to given format string.

How to convert a string to an int in Scala?

A String contains a number like 20. But these are characters. To get an Int we must call a parsing method. We must convert the string. Conversion and parsing. Scala provides many built-in methods to convert Strings, Ints, Lists and Arrays.


2 Answers

sheunis' answer above mostly covers it.

You can coerce an IndexedSeq into an Array with a call to toArray so the first bit's quite straightforward. For the second part, because there's a possible logical branch where you drop through all of your if... else... cases, it's possible for your yield to return both Int and Unit types, whose closest common ancestor is AnyVal.

Note that if you replaced your if... else... with pattern matching instead then you would explicitly get a compiler warning because you're not catching every possible 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 }

like image 185
Mycleung Avatar answered Sep 30 '22 23:09

Mycleung


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, which is why you get an IndexedSeq of Any instead of Int.

like image 24
sheunis Avatar answered Sep 30 '22 23:09

sheunis