2016-05-24 11 views
0

Ich weiß, es gibt verschiedene Bibliotheken um CSV in scala zu lesen. Ich habe den formlosen Weg versucht, aber ich habe Probleme beim Lesen von CSV in generischer Weise für eine Hierarchie. Für z.B. Ich brauche etwas wie folgt aus:Generische Art CSV der Klassenhierarchie in Scala zu lesen

abstract class A 
case class ChildOneOfA(i:Int,s:String) extends A 
case class ChildTwoOfA(i:Int,os:Option[String]) extends A` 



// Requires generic implementation of T which is subtype of A 

def genericCSVReader[T]:GenericCsvRecordReader[T] = { 
//Generic implementation to return csv record iterator/reader 
} 
+0

Können Sie sagen, wie Sie diese ADT als CSV darstellen würden? –

+0

Die Absicht ist, dass csv sich an den Typparameter von Fallklassen halten würde. Wie für 'ChildOneOfA (i: Int, s: String) 'werde ich' "1, HI \ n 2, HALLO" 'oder für' ChildOneOfA (ich: Int, s: Option [String]) 'kann ich haben '1, \ n 2," HEY "' –

+0

Was wäre, wenn die einzelnen Fallklassen unterschiedliche Zahlen und Typen von Elementen hätten (zB 'Boolean' vs.' Double')? Oder wenn Sie unterschiedliche Fallklassen mit der gleichen Anzahl und Art von Elementen hatten? –

Antwort

2

Zunächst einmal Ihr Beispiel ist ein bisschen komisch - jede Zeile ist entweder ein int und ein String oder ein int und ein optionaler String? Das ist dasselbe wie zu sagen, dass jede Zeile eine int und eine optionale Zeichenkette ist, für die Sie nicht die zwei Alternativen benötigen.

Aber für ein nützliches Beispiel, sagen wir mal, dass jede Zeile entweder ein int und ein boolean oder ein int und eine optionale Schwimmer (und nehmen wir an, dass Sie nicht wollen, Eiter verwenden, \/ oder Xor die Disjunktion zu vertreten):

sealed trait A 
case class Alternative1(i: Int, b: Boolean) extends A 
case class Alternative2(i: Int, of: Option[Float]) extends A 

kantan.csv und seine shapeless-Modul können Sie das eigentlich analysieren ziemlich trivial:

import kantan.csv.ops._ 
import kantan.csv.generic._ 

"""1,true 
2,3.14 
3,""".asCsvReader[A](',', false).foreach(println _) 

asCsvReader gebracht wird im Umfang durch die Importaussage. Sie benötigt einen Typparameter, den Typ, mit dem jede Zeile dekodiert wird, und zwei Werteparameter, das Spaltentrennzeichen und ein Flag, das angibt, ob die erste Zeile übersprungen werden soll.

Dieser Code gibt:

Success(Alternative1(1,true)) 
Success(Alternative2(2,Some(3.14))) 
Success(Alternative2(3,None)) 

Beachten Sie, dass:

  • der Rückgabewert von asCsvReader eine Iterator artige Struktur ist, die bedeutet, dass Sie die gesamte CSV nie in den Speicher laden müssen.
  • jede Zeile ist in einem Success oder Failure gewickelt, und Decodierung wirft nie (es sei denn, Sie müssen es tun, in diesem Fall können Sie asUnsafeCsvReader verwenden).
+0

Zur Klärung der Vielfalt der zu erwartenden Fallklassen habe ich unter der Frage kommentiert. Zweitens habe ich versucht, die Bibliothek mit '// vorbei seperator und Header dynamisch in meinem Programm neue Datei (Dateiname) .asCsvReader [T] (seperator, header = Header)' ich 'konnte nicht gefunden impliziter Wert für den Beweisparameter des Typs kantan.csv.RowDecoder [T] ' –

+0

Ich denke, ich sehe das Problem. Es funktioniert nicht mit der abstrakten Klasse. Es funktioniert mit den Eigenschaften in Ordnung. –

+0

Es ist nicht der Unterschied zwischen Merkmal und Abstrakt, sondern die Tatsache, dass es versiegelt werden muss. –

Verwandte Themen