在我的应用程序的几个不同位置,我需要Seq[SalesRow]
并返回Map[String,SalesRow]
,其中字符串是国家/地区的名称。
我需要在几个地方使用它。例如,我列出了所有SalesRows,并按国家/地区获得销售额的全球细分。但在其他地方,我希望按月分解我的销售额,然后按国家/地区分解(Map[Month,Seq[SalesRow]]
变为Map[Month,Map[String,Seq[SalesRow]]]
) - 在其他地方,我希望按天分解,然后按国家/地区分解。
我的问题是:我在哪里放置(小)数量的Seq[SalesRow]
逻辑并将国家/地区的地图返回到行?现在,我将它放在一个伴随对象方法SalesRow.byCountry(rows : Seq[SalesReport]
中。这是最佳的吗?
我想到了一个稍微疯狂的想法,即创建从Seq[SalesRow]
到EnhancedSalesRowSeq
的隐式转换,它具有byCountry
实例方法。这对我很有吸引力,因为该操作适用于任何SalesRows序列。
这是个好主意吗?
将伴侣对象的逻辑添加到我的最佳选择中,还是有更好的选择?
感谢。
答案 0 :(得分:2)
如果表现不是您的主要考虑因素,您可以将逻辑放在:
class RichTraversable[A](t: Traversable[A]) {
def toMapBy[B](f: A => B): Map[B,A] = t.map{ e => (f(e),e) }.toMap
}
因此,如果进行隐式转换,您可以将每个Seq
转换为Map
,并将成员作为关键。
答案 1 :(得分:2)
如果您不知道该库附带groupBy
功能。基本上给定Seq[SalesRow]
,它会根据Map[T, Seq[SalesRow]]
到SalesRow
的函数为您提供T
。
因此,如果您的功能很简单,您可以轻松获得地图。我确实喜欢你对增强型seq的想法,并将隐含放在SalesRow
伴侣中:
case class SalesRow(val month:Int, val country:String,
val person:String, val amount:Float)
class EnhancedRow(rows: Seq[SalesRow]) {
def byCountry: Map[String, Seq[SalesRow]] =
rows.groupBy(_.country)
def byMonth: Map[Int, Seq[SalesRow]] =
rows.groupBy(_.month)
def byCountryByMonth: Map[String, Map[Int, Seq[SalesRow]]] = byCountry.mapValues(r => new EnhancedRow(rows).byMonth)
}
object SalesRow {
implicit def toEnhanced(rows: Seq[SalesRow]) = new EnhancedRow(rows)
}
object Test {
def main(args:Array[String] = null) {
val seq: Seq[SalesRow] = // ... fill this
println(seq.byCountry)
println(seq.byCountryByMonth)
// same as:
println(seq.byCountry.mapValues(_.byMonth))
}
}
答案 2 :(得分:1)
我建议你制作封装类:
case class AllSalesTable(rows: Seq[SalesRow]) {
def toSalesByCountry: SalesByCountry
}
case class ContrySalesTable(rows: Seq[SalesRow])
case class SalesByCountry(map: Map[String, CountrySalesTable])
有一个地方可以放置这种方法是一个好处,但另一个好处是,你可以在这里和那里以简单的“.rows
”为代价获得更大的类型安全性。