2013-09-03 2 views
1

У меня есть дела класс как:Условная группа по Scala в

case class ReportData(
    building: Option[String] = None, 
    serial: Option[String] = None, 
    `type`: Option[String] = None, 
    model: Option[String] = None, 
    machine: Option[String] = None) 

и других областях тоже.

У меня есть список этих объектов, например:

val reports = List(report1, report2, report3, report11, report12)

Запрос должны сделать некоторые конкретные сложные операции с определенными полями этого класса, например, группы перечисляют только на полях, полученных в качестве параметра: groupFields="building,serial"

Это пример тонкой группы по:

val reportsGroupBoth = reports.groupBy(p => (p.building.getOrElse(""), p.serial.getOrElse("")))

, но я хочу сделать это условным в зависимости от полученных полей, поэтому единственный способ, который я собираюсь сделать, - сделать группу разделенной для каждого поля (я добавлю if condition позже. Я просто хочу получить тот же результат, что и выше group by if Я делаю их отделили, результат того типа: Map[(String, String),List[agile.ReportData]]

поэтому я попытался:

// group by building (if building is defined in groupFields list) 
val reportsGroup1 = reports.groupBy(p => p.building) 

это хорошо, но это один неправильно:

// group by building and serial (if building and serial are in groupFields list) 
val reportsGroup2 = reportsGroup1 map { 
     case (key, value) => (key, value.groupBy(v => v.serial).keys) -> value.groupBy(v => v.serial).values 
    } 

Таким образом, вопрос в том, как изменить reportsGroup2, что в конце концов, это будет иметь тот же результат, как reportsGroupBoth из Tpye Map[(String, String),List[agile.ReportData]]

ответ

2

Это будет работать:

val reportsGroup1 = reports.groupBy(p => p.building.getOrElse("")) 

val reportsGroup2 = reportsGroup1 flatMap { 
    case (key, value) => value.groupBy(v => v.serial.getOrElse("")).map { 
    case (key2, value) => ((key, key2), value) 
    } 
} 

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

1

Если вы хотите просто сгруппировать два непустых полей

reports.groupBy(r => (r.building, r.serial)).flatMap({ 
    case ((Some(b),Some(s)),v) => Some((b,s) -> v) 
    case _ => None 
}) 

Если вы хотите группы после группы, как вы предложили:

val reportsGroup2 = reportsGroup1.map({ 
    case (key, value) => value.groupBy(v => (key, v.serial)) 
}).flatten.flatMap({ 
    case ((Some(b),Some(s)),v) => Some((b,s) -> v) 
    case _ => None 
}).toMap 

Вы получите тот же

Может быть вы хотите установить какую-либо политику группировки, например:

val buildingSerialPolicy = 
    Seq[ReportGroup => Option[String](_.building, _.serial) 

А затем необходимо позвонить по телефону:

val removeEmptyKeys = ... 

report.groupBy(r => 
    buildingSerialPolicy.map(_.apply(r))).flatMap(removeEmptyKeys) 
Смежные вопросы