JrPtn
JrPtn

Reputation: 83

Scala: Using Option for key/value pairs in a list

I'm trying to write the get method for a key, value pair implemented using a list. I want to use the Option type as I heard its good for this but I'm new to Scala and I'm not really sure how to use it in this case...

This is as far as I got, only the method header.

def get(key : String): Option[Any] = {}

Upvotes: 2

Views: 3083

Answers (3)

scand1sk
scand1sk

Reputation: 1124

Although @Marius' collectFirst version is probably the most elegant (and maybe a little bit faster as it only uses one closure), I find it more intuitive to use find for your problem :

def get[A, B](key: A, pairs: List[(A, B)]): Option[B] = pairs.find(_._1 == key).map(_._2)

In case you were wondering (or need high performance), you will need either @Marius' recursive or the following imperative version which may look more familiar (although less idiomatic):

def get[A, B](key: A, pairs: List[(A, B)]): Option[B] = {
  var l = pairs
  var found: Option[B] = None
  while (l.nonEmpty && found.isEmpty) {
    val (k, v) = l.head
    if (k == key) {
      found = Some(v)
    } else {
      l = l.tail
    }
  }
  found
}

What you must understand is that Option[B] is a class that may either be instantiated to None (which replaces and improves the null reference used in other languages) or Some(value: B). Some is a case class, which allows, among other neat features, to instantiate it without the new keyword (thanks to some compiler magic, Google Scala case class for more info). You can think of Option as a List which may contain either 0 or 1 element: most operations that can be done on sequences can also be applied to Options (such as map in the find version).

Upvotes: 0

Channing Walton
Channing Walton

Reputation: 4007

You can turn a List of Pairs into a Map:

class Store[K, V](values: List[(K, V)]) {
  val map = values.toMap
  def get(key: K): Option[V] = map get key
}

Upvotes: 0

Marius Danila
Marius Danila

Reputation: 10401

My guess is you are looking for something like this:

class KeyValueStore(pairs: List[(String, Any)]) {

  def get(key: String): Option[Any] = pairs.collectFirst {
    case (k, v) if k == key => v
  }

}

This uses the collectFirst method for sequences. If you want a more "do it yourself" approach, this should work:

def get(key: String): Option[Any] = {
  def search(xs: List[(String, Any)]): Option[Any] = {
    xs match {
      case List() => None //end of list and key not found. We return None
      case (k, v) :: rest if k == key => Some(v) // found our key. Returning some value
      case _ :: rest => search(rest) // not found until nou. Carrying on with the rest of the list
    }

    search(pairs)
  }
}

Upvotes: 3

Related Questions