Kamal Kishore
Kamal Kishore

Reputation: 325

Fetch elements from Option[Any] of List

scala> val a  = jsonMap.get("L2_ID")
a: Option[Any] = Some(List(24493, 22774, 23609, 20517, 22829, 23646, 22779, 23578, 22765, 23657))

I want to fetch the first element of list i.e 24493. So, tried below code:

scala> var b = a.map(_.toString)
b: Option[String] = Some(List(24493, 22774, 23609, 20517, 22829, 23646, 22779, 23578, 22765, 23657))

scala>

scala>  var c = b.map(_.split(",")).toList.flatten
c: List[String] = List(List(24493, " 22774", " 23609", " 20517", " 22829", " 23646", " 22779", " 23578", " 22765", " 23657)")

scala> c(0)
res34: String = List(24493

This is not returning as expected.

Upvotes: 0

Views: 1065

Answers (3)

Andrey Tyukin
Andrey Tyukin

Reputation: 44957

If you are certain that it's a Some, and that the list is non-empty, then you can unwrap the option and get the List[Int] using .get. Then you can access the first element of the list using .head:

val x: Option[List[Int]] = ???
x.get.head

If you are not in the REPL, and if you aren't sure whether it's a Some or None, and whether the List has any elements, then use

x.flatMap(_.headOption).getOrElse(yourDefaultValueEg0)

"Stringly-typed" programming is certainly not necessary in a language with such a powerful type system, so converting everything to string and splitting by commas was a seriously flawed approach.

Upvotes: 2

Dima
Dima

Reputation: 40510

So, you have an Option, and List inside of it. Then scala> var b = a.map(_.toString) converts the contents of the Option (a List) into a String. That's not what you want. Look at the types of the results of your transformations, they are there to provide pretty good hints for you. b: Option[String], for example, tells you that you have lost the list ...

 a.map(_.map(_.toString))

has the type Option[List[String]] on the other hand: you have converted every element of the list to a string.

If you are just looking for the first element, there is no need to convert all of them though. Something like this will do:

 a
  .flatMap(_.headOption) // Option[Int], containing first element or None if list was empty or id a was None
  .map(_.toString) // convert Int inside of Option (if any) to String
  .getOrElse("")   // get the contents of the Option, or empty string if it was None

Upvotes: 2

Philipp
Philipp

Reputation: 977

I suggest you use pattern matching. To be defensive, i also added a Try to protect against the case of your json not being a List of numbers. Code below returns an Option[Int] and you can call .getOrElse(0) on it - or some other default value, if you like.

import scala.util.Try

val first = a match {
  case Some(h :: _) => Try(h.toString.toInt).toOption
  case _ => None
}

Upvotes: 4

Related Questions