I am implementing some kind of "record matrix" where the axis indices are (unique) keys of some type K (eg. String). These keys doesn't need to be sorted but I need an order, so I went for a SortedSet.
The main purpose of the keys (SortedSet) are to find the actual integer index in the underlying 2 dimensional data array (Seq[Seq[.]] or what ever).
But I cannot find a ways to get such a f(key: K): Int function.
Instead of a SortedSet[K], I could use a Map[K,Int] which values are the indices, but I find that overkill (and not well typed).
Any idea?
Edit
The Map method is something like, but in 2D:
val myKeys = // SortedSet("A", "B", "C")
val data = // Array(13,42,117)
val keyIndices = myKeys.zipWithIndex.toMap
// get indices of "B", and lookup in data array
data(keyIndices("B"))
I wrote "not well typed" for the Map solution because the type does not guaranty the indices are consecutive and starting at 0. While the position in an ordered seq is.
Selected solution
I selected Neumann's answer because it was best for my actual problem. But Cipcigan's and Verkerk's answers suits more the title.
Using zipWithIndex should do it:
def getIndex[T](xs: scala.collection.SortedSet[T], x:T): Option[Int] =
xs.zipWithIndex.find(_._1 == x).map(_._2)
val a = scala.collection.SortedSet("a", "l", "m", "o", "n", "d")
getIndex(a, "a") // => Some(0)
getIndex(a, "m") // => Some(3)
getIndex(a, "x") // => None
Keeping theSet you can not. Having a way to get an element by index is a trait of a Seq.
scala> val data =scala.collection.SortedSet("a", "l", "m", "o", "n", "d")
data: scala.collection.SortedSet[String] = TreeSet(a, d, l, m, n, o)
scala> data(1)
<console>:12: error: type mismatch;
found : Int(1)
required: String
data(1)
^
scala> data("a")
res3: Boolean = true
I this example it is shown that the apply method checks if given argument is contained in the set.
I would go with the approach you already suggested by using the Map. Or transform the data to a Seq
scala> val indexedData = data.toVector
indexedData: Vector[String] = Vector(a, d, l, m, n, o)
scala> indexedData(2)
res9: String = l
scala> indexedData.indexOf("l")
res1: Int = 2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With