不了解groupBy方法

时间:2015-08-13 09:48:04

标签: scala

groupBy定义为:def groupBy[K](f: A => K): immutable.Map[K, Repr] = {

所以f是一个函数,它取A并返回K,K是当前类型所以下面的例子是List?

使用以下内容:

  val l : List[(String , String)] = List( ("a" , "line1") , ("b" , "line2") , ("b" , "line3") , ("a" , "line4"))
  val gm : Map[String,List[(String, String)]] = l.groupBy(_._1)

我试图转换为类型:

  val m : Map[String , List[String]] = Map("a" -> List("line1" , "line4") , "b" -> List("line2" , "line3"))

但我收到类型:Map[String,List[(String, String)]]

如何修改groupBy(_._1)以返回例外类型?为什么_._1A => K类型的函数?

3 个答案:

答案 0 :(得分:3)

如果我们引入类型别名,可能会更容易理解:

scala> type Key = String
defined type alias Key

scala> type Value = String
defined type alias Value

scala> val l: List[(Key, Value)] = List("a" -> "line1", "b" -> "line2", "b" -> "line3", "a" -> "line4")
// l: List[(Key, Value)] = List((a,line1), (b,line2), (b,line3), (a,line4))

scala> l.groupBy(_._1)
// res0: scala.collection.immutable.Map[Key,List[(Key, Value)]] = Map(b -> List((b,line2), (b,line3)), a -> List((a,line1), (a,line4)))

现在很明显,groupBy从Key(Value,Value)对中取出Key,但是lefts对完整,只是基于Key将它们聚合在一起。我们需要做的是从这些分组对中选择值:

scala> res0.mapValues(group => group.map(kv => kv._2))
// res2: scala.collection.immutable.Map[Key,List[Value]] = Map(b -> List(line2, line3), a -> List(line1, line4))

答案 1 :(得分:1)

groupBy接收类型为Repr的输入集合(在您的情况下为List[(String, String)],并将密钥生成函数 f应用于其中,将Repr的前元素作为值存储在Map[K, Repr]

因此,使用该方法无法同时转换值。您想要提取密钥和值。您想最终得到一种"multi-map"

  

为什么_._1A => K类型的函数?

您的函数会收到输入集合的元素,这是Tuple2个字符串,因此_._1((a: String, b: String)) => a的缩写。

快速解决方案是再次映射结果:

l.groupBy(_._1).map { case (key, list) => (key, list.map(_._2)) }

答案 2 :(得分:1)

你有一个List [(String,String)]然后你对该元组的第一个值进行groupBy,最后得到Map [String,List [(String,String)]]。所以你有正确的密钥,但错误的值。您需要在列表元组中删除第一个值。

可以使用mapValues将列表(复数形式)从List [(String,String)]更改为List [String]:

val l : List[(String , String)] = List( ("a" , "line1") , ("b" , "line2") , ("b" , "line3") , ("a" , "line4"))
val gm : Map[String,List[(String, String)]] = l.groupBy(_._1)
val m : Map[String, List[String]] = gm.mapValues(_.map(_._2))

A是列表的类型,K是您正在创建的新组密钥的类型。函数A => K允许您从列表类型A创建任何类型的密钥类型K.

请注意,列表的A类型保留在地图中的列表中。