2014-01-28 3 views
0

У меня есть строка в этом формате CSV:Функционально преобразовать эту строку в список объектов

//> lines : String = a1 , 2 , 10 
//| a2 , 2 , 5 
//| a3 , 8 , 4 
//| a4 , 5 , 8 
//| a5 , 7 , 5 
//| a6 , 6 , 4 
//| a8 , 4 , 9 

Я хотел бы преобразовать эту строку в список объектов, где каждая строка строки представляет новую запись в списке объектов. Я могу подумать, как это сделать -

Разделите строку на несколько строк и разделите каждую строку на свои токены csv. Перебирайте по каждой строке и для каждой строки создайте новый объект и добавьте его в список. Но я пытаюсь думать об этом функционально, и я не уверен, с чего начать. Любые указатели, пожалуйста?

+1

это простой список понимание – gefei

ответ

3

Не уверен, что это точный результат, который вы хотите, поскольку не было предоставлено выходное изображение выборки. Должно быть, можно получить то, что вы хотите от этого.

scala> val lines: String = """a1,2,10 
| a2,2,5 
| a3,8,4 
| a4,5,8 
| a5,7,5 
| a6,6,4 
| a8,4,9""" 
lines: String = 
a1,2,10 
a2,2,5 
a3,8,4 
a4,5,8 
a5,7,5 
a6,6,4 
a8,4,9 


scala> case class Line(s: String, s2: String, s3: String) 
defined class Line 

scala> lines.split("\n").map(line => line.split(",")).map(split => Line(split(0), split(1), split(2))) 
res0: Array[Line] = Array(Line(a1,2,10), Line(a2,2,5), Line(a3,8,4), Line(a4,5,8), Line(a5,7,5), Line(a6,6,4), Line(a8,4,9)) 
4

Предположим, вы начинаете с итератора, производящего одну строку для каждой строки. Source класс может это сделать, если вы загружаете из файла, или вы можете использовать val lines = input.split("\n"), если вы уже начиная со всем в одном String

Это также работает со списком, послед и т.д. Iterator не предпосылка.

Таким образом, вы карту над входом, чтобы разобрать каждую строку

val lines = input split "\n" 
val output = lines map { line => parse(line) } 

или (в точке свободного стиля)

val output = lines map parse 

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

case class Line(id: String, num1: Int, num2: Int) 

Итак, чтобы разобрать. Я буду слишком обернуть результаты в Try, так что вы можете захватить ошибки:

def parse(line: String): Try[Line] = Try { 
    //split on commas and trim whitespace 
    line.split(",").trim match { 
    //String.split produces an Array, so we pattern-match on an Array of 3 elems 
    case Array(id,n1,n2) => 
     // if toInt fails it'll throw an Exception to be wrapped in the Try 
     Line(id, n1.toInt, n2.toInt) 
    case x => throw new RuntimeException("Invalid line: " + x) 
    } 
} 

Сложите все это вместе, и вы в конечном итоге с выходным будучи CC[Try[Line]], где CC является сбор-типа lines (например итератора , Seq и т.д.)

вы можете изолировать ошибки:

val (goodLines, badLines) = output.partition(_.isSuccess) 

Или, если вы просто хотите, чтобы вырезать промежуточные Try с и отбросить ошибки:

val goodLines: Seq[Line] = output collect { case Success(line) => line } 

ВСЕ ВМЕСТЕ

case class Line(id: String, num1: Int, num2: Int) 

def parse(line: String): Try[Line] = Try { 
    line.split(",").trim match { 
    case Array(id,n1,n2) => Line(id, n1.toInt, n2.toInt) 
    case x => throw new RuntimeException("Invalid line: " + x) 
    } 
} 

val lines = input split "\n" 
val output = lines map parse 
val (successes, failures) = output.partition(_.isSuccess) 
val goodLines = successes collect { case Success(line) => line } 
Смежные вопросы