我是Scala的新手,正在尝试进行一些数据分析。
我有一个带有几个标题的CSV文件-可以说商品编号,商品类型,月份,出售商品。
我制作了带有标题字段的Item类。我将CSV拆分为一个列表,列表的每次迭代都是由Item类表示的CSV文件的一行。
我正在尝试创建一种基于发送的参数来创建地图的方法。例如,如果我想按月份或按商品类型对出售的商品进行分组。但是,我正在努力将Item.field发送到方法中。
Fee我正在尝试的是类似的东西:
makemaps(Item.month);
makemaps(Item.itemtype);
def makemaps(Item.field):
if (item.field==Item.month){}
else (if item.field==Item.itemType){}
但是我对此的逻辑似乎是错误的。有什么想法吗?
def makeMap[T](items: Iterable[Item])(extractKey: Item => T): Map[T, Iterable[Item]] =
items.groupBy(extractKey)
因此给出此示例Item
类:
case class Item(month: String, itemType: String, quantity: Int, description: String)
您可能有(我相信类型说明是必填的:]
val byMonth = makeMap[String](items)(_.month)
val byType = makeMap[String](items)(_.itemType)
val byQuantity = makeMap[Int](items)(_.quantity)
val byDescription = makeMap[String](items)(_.description)
例如,注意_.month
创建一个采用Item
的函数,该函数导致String
字段中包含的month
(略微简化)。
[如果愿意,可以将用于提取键的功能保存在伴随对象中:
object Item {
val month: Item => String = _.month
val itemType: Item => String = _.itemType
val quantity: Item => Int = _.quantity
val description: Item => String = _.description
// Allows us to determine if using a predefined extractor or using an ad hoc one
val extractors: Set[Item => Any] = Set(month, itemType, quantity, description)
}
然后您可以像这样传递这些内容:
val byMonth = makeMap[String](items)(Item.month)
唯一真正的语义上的变化是,您在运行时显式避免了可能的多余lambda构造,但代价是要让lambda始终停留在内存中。附带的好处是,如果您确定源Item
永不更改,则可以通过提取器缓存地图:对于lambda,相等是引用相等。如果您有一些表示Item
集合的类,而不是仅使用标准集合,则这可能特别有用。