2013-02-20 2 views
7

Я хотел бы разделить строку на пробелы, который имеет 4 элемента:Scala разделить строку на кортеж

1 1 4.57 0.83 

и я пытаюсь преобразовать в список [(String, String, Point)] таким образом, что первые два splits - это первые два элемента в списке, а последние два - Point. Я делаю следующее, но это не похоже на работу:

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 
+1

Если вы хотите кортеж, почему вы говорите, что хотите преобразовать в список? –

+0

Я согласен, это скорее всего будет озаглавлено ближе к преобразованию строки в List() элементов –

ответ

8

Вы можете использовать шаблон, соответствующий извлечь то, что вам нужно из массива:

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))) 
    }) 
+1

Это не компилируется для меня, я добавил еще один похожий ответ, который компилируется - я не мог заставить код правильно отображаться в комментариях. Мне было бы интересно узнать, как можно использовать коллекцию, если кто-то еще знает. –

+0

из API 'collect' *" Создает новую коллекцию, применяя частичную функцию ко всем элементам этого списка, на которых определена функция. "*. Это как «карта», но оставляет только элементы в области частичной функции. –

1

Вы не преобразование третьих и четвертые маркеров Point, ни вы преобразование строки в List. Кроме того, вы не обрабатываете каждый элемент как Tuple3, а как List.

Следующее должно быть в соответствии с тем, что вы ищете.

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 
+0

PS: Я не тестировал это. – cheeken

+0

Класс My Point принимает (IndexedSeq [Double]), так как я могу получить Indexed Seq из кортежа? –

13

Как об этом:

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)) 
+0

Простой и понятный. Возможно, вы захотите добавить случай для обработки ошибок ввода. –

-1

Есть способы, чтобы преобразовать Кортеж к списку или Seq , Один из способов:

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

Бу т, как вы можете видеть, что тип возвращаемого значения Любой и НЕ INTEGER

Для преобразования в различные типы вы используете Hlist из https://github.com/milessabin/shapeless

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))) 
} 

А для любопытных, @ в шаблоне сопоставление связывает переменную с шаблоном, поэтому points @ _* связывает переменные точки с шаблоном * _ И * _ соответствует остальной части массива, поэтому точки заканчиваются как Seq [String].

+0

Хм .. Я получаю scala.MatchError: [Ljava.lang.String; @ 7bfacd5d (из класса [Ljava.lang.String;) Что я делаю неправильно? – Sergey

Смежные вопросы