如何处理特定类型的集合的操作?

时间:2011-04-30 18:40:44

标签: oop scala implicits

在我的应用程序的几个不同位置,我需要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序列。

这是个好主意吗?

将伴侣对象的逻辑添加到我的最佳选择中,还是有更好的选择?

感谢。

3 个答案:

答案 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”为代价获得更大的类型安全性。