2011-04-30 55 views
3

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

这是个好主意吗?

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

谢谢。

回答

2

如果您不知道该库附带groupBy函数。基本上给一个Seq[SalesRow]它会给你一个Map[T, Seq[SalesRow]]基于从SalesRowT的功能。

所以,如果你的功能很容易,你可以很容易地得到一张地图。我喜欢你的增强序列的想法连同把隐含在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

如果性能isn't您的主要关注,你可以把逻辑的:

class RichTraversable[A](t: Traversable[A]) { 
    def toMapBy[B](f: A => B): Map[B,A] = t.map{ e => (f(e),e) }.toMap 
} 

所以如果一个隐式转换,你可以把每一个SeqMap与成员是关键。

+0

对,这就是我在倒数第二段提出的建议。我的问题是:这是一件非常奇怪或意想不到的事情吗? – Bill 2011-05-01 01:20:27

+0

这或多或少等同于'groupBy',它是一个库定义的方法。 – huynhjl 2011-05-01 02:06:13

+0

从@huynhjl的评论中可以推断出这并不出人意料,这是对我重新推演图书馆方法的疏忽。 – 2011-05-01 08:19:47

1

我建议你做封装类:

case class AllSalesTable(rows: Seq[SalesRow]) { 
    def toSalesByCountry: SalesByCountry 
} 

case class ContrySalesTable(rows: Seq[SalesRow]) 

case class SalesByCountry(map: Map[String, CountrySalesTable]) 

有地方可放的方法是一个好处,但另一个好处是您可以在这里和那里以简单的“.rows”为代价获得更高的安全性。

+0

我同意丹尼尔!我的经验是,即使对于简单的数据结构,使用类或类型defs也可以提供更清晰的代码,编译器通常可以提供帮助。 – 2011-05-01 17:55:28