i.am.michiel
i.am.michiel

Reputation: 10404

How to create a List in Scala from existing list with type conversion?

Context

I've got a List like this :

List[(User)]

and I need a List like this :

List[(String, String)]

With a user defined as following :

case class User(
    id:Pk[Long] = NotAssigned, 
    name: String
)    

If fact, the initial list is build from classes :

Tried :

My first "naive" attempt (coming from Java) was :

myList.map { u => u.id.get.toString, u.name }

And I've got a error :

required List[(String, String)] 
given List[(java.lang.String, String)]

Solution

As mentioned in the post referenced in comment, Scala has a String type which is a extending java.lang.String. When using inference, Scala is not going to convert to the Scala super class. In order to use the Scala String type, you have to explicitly define the return type.

Exemple :

// Returns List[(java.lang.String, String)]
myList.map { u => u.id.get.toString, u.name }

// Returns List[(String, String)]
def convert(m:List[User]):List[(String, String)] = {
    m.map { u => u.id.get.toString, u.name }    
}

Upvotes: 2

Views: 745

Answers (5)

Jan
Jan

Reputation: 1777

This works in my REPL:

scala> case class User (id: Option[Long] = None, name:String)
defined class User

scala> val users = User(name = "Name") :: User(name = "LastName") :: Nil
users: List[User] = List(User(None,Name), User(None,LastName))

scala> val pairs = users.map{u => u.id.toString -> u.name}
pairs: List[(String, String)] = List((None,Name), (None,LastName))

Upvotes: 2

missingfaktor
missingfaktor

Reputation: 92066

You are close. Just need to add parentheses.

myList.map { u => (u.id.get.toString, u.name) }

Or you could use the extractor for User.

myList.map { case User(id, name) => (id.get.toString, name) }

Upvotes: 4

Edmondo
Edmondo

Reputation: 20090

Why this won't work?

def method(a:List[(Long,String)]):List[(String,String)] = a.map { case (value1,value2) => (value1.toString,value2)}

Upvotes: 4

om-nom-nom
om-nom-nom

Reputation: 62835

How about:

myList.map(t => t._1+"" -> t._2)

or alternatively:

myList.map { case(k,v) => (k.toString, v) }

Upvotes: 1

Malte Schwerhoff
Malte Schwerhoff

Reputation: 12852

val xs: List[(Long, String)] = List((1l, "A"), (2l, "B"))
val ys: List[(String, String)] = xs.map{case (a, b) => (a.toString, b)}

In the above solution, a partial function (which actually happens to be a total one for the given domain) is uses for the sake of being able to decompose the tuple into its constituents (here a and b).

You can also use the tuple's accessor methods to get to the components:

val zs: List[(String, String)] = xs.map(t => (t._1.toString, t._2))

Upvotes: 1

Related Questions