2016-05-16 31 views
0

Ich habe 2 Fall-Klassen:Scala Kartensammlung Fall-Klasse Karte()

case class OutlierPortal(portal: String, timeData: Seq[OutlierPortalTimeSeriesData]) 

und

case class OutlierPortalTimeSeriesData(period: Timestamp, totalAmount: Double, isOutlier: Int) 

bzw. ein Seq[OutlierPortal]

Was ich ausführen möchte, ist ähnlich zu Scala Macros: Making a Map out of fields of a class in Scala, aber ich möchte eine Sequenz einer (verschachtelten) Fall-Klassen zu Seq[Map[String, Any]] zuordnen.

Allerdings neu für scala ich fürchte ein bisschen die vorgeschlagene Idee von Makros. Gibt es einen "einfacheren" Weg, diese Sequenz von Seq[OutlierPortal] zu Seq[Map[String, Any]]

zu mappen Oder würden Sie empfehlen, Makros zu verwenden, obwohl ein Anfänger in scala? Für mich ist eine einseitige Konvertierung (Fallklasse -> Karte) ausreichend.

+0

Um klar zu sein, du willst vermeiden, die Strings hart zu codieren? –

+0

Flexible Schlüssel wären nett, aber nicht zwingend notwendig –

+0

Sie wollen den 'Wert' des Typs' Any' mit den Feldern value? –

Antwort

4

Wenn Sie versuchen, ausgefallene Tricks zu vermeiden, und Sie nicht zu viele Gesamtklassen haben, um dies zu schreiben, können Sie einfach die Methoden zum Erstellen der Karten selbst schreiben. Ich würde vorschlagen, Methoden wie etwa toMap zu Ihren Fallklassen hinzuzufügen. OutlierPortalTimeSeriesData ‚s ist einfach, wenn Sie die Map() Konstruktor verwenden:

case class OutlierPortalTimeSeriesData(period: Timestamp, totalAmount: Double, isOutlier: Int) { 
    def toMap: Map[String, Any] = Map(
    "period" -> period, 
    "totalAmount" -> totalAmount, 
    "isOutlier" -> isOutlier) 
} 

Ich nehme an, es gibt einige Überschneidungen gibt, aber zumindest, wenn Sie jemals einen Grund haben die String-Werte zu ändern, aber nicht die Variablennamen haben Sie die Flexibilität das zu tun.

Um eine Folge von etwas nehmen Sie toMap auf, und schalten Sie ihn in eine Seq[Map[String, Any]] einfach anrufen können, verwenden map:

case class OutlierPortal(portal: String, timeData: Seq[OutlierPortalTimeSeriesData]) { 
    def toMap: Map[String, Any] = Map(
    "portal" -> portal, 
    "timeData" -> timeData.map { _.toMap }) 
} 
:

mySeq.map { _.toMap } 

Wir diese können sowohl OutlierPortal ‚s toMap zu schreiben

und dann wieder um eine Seq[OutlierPortal] in eine Seq[Map[String, Any]] zu konvertieren.

Je nachdem, wie Sie diese Objekte und Methoden verwenden, Sie könnten ein Merkmal definieren wollen, die Klassen mit dieser Methode unterscheidet, und haben Ihren Fall Klassen erweitern es:

trait HasToMap { def toMap: Map[String, Any] } 
case class Blah(/* ... */) extends HasToMap { 
    def toMap: /* ... */ } 
} 

Dies würde Sie nehmen ein Wert, von dem Sie wissen, dass Sie ihn in Map[String, Any] (oder eine Folge von ihnen usw.) in einer Methode umwandeln können, die sich ansonsten nicht darum kümmert, um welchen bestimmten Typ es sich handelt.

+0

Implementieren dieser Lösung für jetzt bekomme ich den folgenden Fehler: 'def mapOutliersForJobserver (Ausreißer: Future [Seq [OutlierPortal]]): Future [Seq [Karte [String, Beliebige]]] = { outliers.map (_.toMap) } 'Fehler:' Future [Map [Nichts, nichts]] entspricht nicht dem Typ Future [Seq [Map [String, Any]]] 'Was ist das Problem hier? Ist es die Seq [T]? –

+0

@geoHeil Sie versuchen, eine 'Future [Seq [T]]' wie eine 'Seq [T]' zu behandeln. Sie sind jedoch anders, genau wie ein Seq [Seq [T]]. –

+0

@geoHeil, also könnten Sie zum Beispiel zwei verschachtelte Aufrufe verwenden, um 'map' wie' {outliers.map {_.map {_.toMap}} '' 'zuzuordnen. Es muss jedoch einen saubereren Weg geben. –