2016-05-16 2 views
0

У меня есть 2 тематические классы:Scala карта коллекция случай-класс Карта()

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

и

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

или, соответственно, в Seq[OutlierPortal]

То, что я хочу, чтобы выполнить аналогично до Scala Macros: Making a Map out of fields of a class in Scala, но я хочу отобразить последовательность (вложенных) классов case в Seq[Map[String, Any]].

Однако, новый для scala немного боюсь предлагаемой идеи макросов. Есть ли более простой способ сопоставить эту последовательность Seq[OutlierPortal] с Seq[Map[String, Any]]

Или вы бы рекомендовали начать использовать макросы, даже если новичок в scala? Для меня достаточно одностороннего преобразования (case-class -> map).

+0

Чтобы быть ясным, вы хотите избежать жесткого кодирования строк? –

+0

Гибкие клавиши были бы хорошими, но не обязательными. –

+0

Вы хотите, чтобы 'значение' типа' Any' содержало значение полей? –

ответ

4

Если вы хотите избежать причудливых трюков, и у вас не слишком много общих классов, чтобы написать это, вы можете просто написать методы для создания карт самостоятельно. Я бы предложил добавить методы, названные как toMap, к вашим классам case. OutlierPortalTimeSeriesData «s прост, если вы используете Map() конструктор:

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

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

Для того, чтобы последовательность то, что вы можете позвонить toMap дальше, и превратить его в Seq[Map[String, Any]], просто использовать map:

mySeq.map { _.toMap } 

Мы можем использовать это как писать OutlierPortal «s toMap:

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

, а затем еще раз для преобразования Seq[OutlierPortal] в Seq[Map[String, Any]].

В зависимости от того, как вы используете эти объекты и методы, вы можете определить черту, отличающую классы с помощью этого метода, и ваши классы случае продлить его:

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

Это позволит вам принять значение, которое, как вы знаете, можно преобразовать в Map[String, Any] (или их последовательность и т. д.) в методе, который в противном случае не заботится о том, какой именно тип он есть.

+0

Реализация этого решения на данный момент я получаю следующую ошибку: 'def mapOutliersForJobserver (outliers: Future [Seq [OutlierPortal]]): Future [Seq [Map [String, Any]]] = { outliers.map (_.toMap) } 'error:' Future [Map [Nothing, Nothing]] не соответствует типу Future [Seq [Map [String, Any]]] 'В чем проблема? ist это Seq [T]? –

+0

@geoHeil Вы пытаетесь рассматривать «Будущее [Seq [T]]» так же, как 'Seq [T]'. Однако они отличаются друг от друга, как и 'Seq [Seq [T]]'. –

+0

@geoHeil, например, вы можете использовать два вложенных вызова для 'map', например' {outliers.map {_.map {_.toMap}} '. Однако должен быть более чистый способ сделать это. –

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