16

I would like to split a string on whitespace that has 4 elements:

1 1 4.57 0.83

and I am trying to convert into List[(String,String,Point)] such that first two splits are first two elements in the list and the last two is Point. I am doing the following but it doesn't seem to work:

Source.fromFile(filename).getLines.map(string => { 
            val split = string.split(" ")
            (split(0), split(1), split(2))
        }).map{t => List(t._1, t._2, t._3)}.toIterator
2
  • 1
    If you want a tuple why are you saying you want to convert to a List? Commented Feb 20, 2013 at 3:47
  • I agree, this should likely be titled closer to convert string to List() of elements Commented Dec 4, 2013 at 0:40

5 Answers 5

18

How about this:

scala> case class Point(x: Double, y: Double)
defined class Point

scala> s43.split("\\s+") match { case Array(i, j, x, y) => (i.toInt, j.toInt, Point(x.toDouble, y.toDouble)) }
res00: (Int, Int, Point) = (1,1,Point(4.57,0.83))
Sign up to request clarification or add additional context in comments.

1 Comment

Simple and clear. You might want to add a case for handling input errors.
15

You could use pattern matching to extract what you need from the array:

    case class Point(pts: Seq[Double])
    val lines = List("1 1 4.34 2.34")

    val coords = lines.collect(_.split("\\s+") match {
      case Array(s1, s2, points @ _*) => (s1, s2, Point(points.map(_.toDouble)))
    })

2 Comments

This doesn't compile for me, I added another similar answer that does compile - I couldn't get the code to show up properly in comments. I would be curious to see how collect could be used if someone else knows.
from the API of collect "Builds a new collection by applying a partial function to all elements of this list on which the function is defined.". It's just like map but leaves only the elements in the domain of the partial function
1

You are not converting the third and fourth tokens into a Point, nor are you converting the lines into a List. Also, you are not rendering each element as a Tuple3, but as a List.

The following should be more in line with what you are looking for.

case class Point(x: Double, y: Double) // Simple point class
Source.fromFile(filename).getLines.map(line => { 
    val tokens = line.split("""\s+""") // Use a regex to avoid empty tokens
    (tokens(0), tokens(1), Point(tokens(2).toDouble, tokens(3).toDouble))
}).toList // Convert from an Iterator to List

1 Comment

My Point class takes (IndexedSeq[Double]) so how do I get Indexed Seq from tuple?
1
case class Point(pts: Seq[Double])
val lines = "1 1 4.34 2.34"

val splitLines = lines.split("\\s+") match {
  case Array(s1, s2, points @ _*) => (s1, s2, Point(points.map(_.toDouble)))
}

And for the curious, the @ in pattern matching binds a variable to the pattern, so points @ _* is binding the variable points to the pattern *_ And *_ matches the rest of the array, so points ends up being a Seq[String].

1 Comment

Hm.. I'm getting scala.MatchError: [Ljava.lang.String;@7bfacd5d (of class [Ljava.lang.String;) What do I do wrong?
-1

There are ways to convert a Tuple to List or Seq, One way is

scala> (1,2,3).productIterator.toList
res12: List[Any] = List(1, 2, 3)

But as you can see that the return type is Any and NOT an INTEGER

For converting into different types you use Hlist of https://github.com/milessabin/shapeless

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.