如何在Scala中泛化类型参数
我有一个我称之为groupBy的配对列表。但是,groupBy在值中包含了该对的两个部分,我只想包含该对中没有“分组依据”的部分 scala.collection.immutable.Map[Int,List[(Int,Int)]]=Map(1-> 列表((1,2)、(1,3)),2->List((2,3))) 我编写了一个方法来映射映射条目并删除复制键:如何在Scala中泛化类型参数,scala,types,Scala,Types,我有一个我称之为groupBy的配对列表。但是,groupBy在值中包含了该对的两个部分,我只想包含该对中没有“分组依据”的部分 scala.collection.immutable.Map[Int,List[(Int,Int)]]=Map(1-> 列表((1,2)、(1,3)),2->List((2,3))) 我编写了一个方法来映射映射条目并删除复制键: def removeDupeKeyFromPair[A, B](m: Map[A, List[Pair[A, B]]]): Map[A, L
def removeDupeKeyFromPair[A, B](m: Map[A, List[Pair[A, B]]]): Map[A, List[B]] =
m map { case(k, vlist) => k -> { vlist map { case(dupe, b) => b } } }
但是,我想将其从
List[Pair[A,B]]
推广到C[Pair[A,B]]
,其中C如果您只想更改Map
值,您可以使用mapValues
:
scala> List(1->2, 1->3, 2->3) groupBy (_._1) mapValues (_.map(_._2))
res2: scala.collection.immutable.Map[Int,List[Int]] = Map(2 -> List(3), 1 -> List(2, 3))
或者以更具可读性的方式:
scala> List(1->2, 1->3, 2->3) groupBy (_._1) mapValues (lst => lst.map { case(_ ,b) => b })
res3: scala.collection.immutable.Map[Int,List[Int]] = Map(2 -> List(3), 1 -> List(2, 3))
如果您只想更改映射
值,可以使用映射值
:
scala> List(1->2, 1->3, 2->3) groupBy (_._1) mapValues (_.map(_._2))
res2: scala.collection.immutable.Map[Int,List[Int]] = Map(2 -> List(3), 1 -> List(2, 3))
或者以更具可读性的方式:
scala> List(1->2, 1->3, 2->3) groupBy (_._1) mapValues (lst => lst.map { case(_ ,b) => b })
res3: scala.collection.immutable.Map[Int,List[Int]] = Map(2 -> List(3), 1 -> List(2, 3))
使用C有什么意义?使用C有什么意义?为了使这些东西更通用,您可以使用专门的类型类。用于map
和flatMap
等方法的是FilterMonadic
FilterMonadic
将其映射方法指定为使用CanBuildFrom
。大多数内置集合类都有一个可用的集合类。然后您可以这样使用它:
def removeDupeKeyFromPair[A, B,
// Define a type C that has type arguments and extends FilterMonadic
C[X] <: FilterMonadic[X, C[X]],
// Define the type that will be returned (provided by the implicit CanBuildFrom)
That](
// Use C instead of List
m: Map[A, C[(A, B)]])(
// Define the CanBuildFrom that is required by the map method
implicit bf:CanBuildFrom[C[(A, B)], B, That]): Map[A, That] =
// actual logic
m.map { case (k, vlist) =>
k -> vlist.map { case (dupe, b) => b }
}
def从对[A,B,
//定义具有类型参数并扩展FilterMonadic的类型C
C[X]
k->vlist.map{case(dupe,b)=>b}
}
编辑
请注意,我使用了(A,B)
符号,而不是对[A,B]
,为了使这些东西更通用,您可以使用专门的类型类。用于map
和flatMap
等方法的是FilterMonadic
FilterMonadic
将其映射方法指定为使用CanBuildFrom
的映射方法。大多数内置集合类都有可用的映射方法之一。然后,您可以这样使用它:
def removeDupeKeyFromPair[A, B,
// Define a type C that has type arguments and extends FilterMonadic
C[X] <: FilterMonadic[X, C[X]],
// Define the type that will be returned (provided by the implicit CanBuildFrom)
That](
// Use C instead of List
m: Map[A, C[(A, B)]])(
// Define the CanBuildFrom that is required by the map method
implicit bf:CanBuildFrom[C[(A, B)], B, That]): Map[A, That] =
// actual logic
m.map { case (k, vlist) =>
k -> vlist.map { case (dupe, b) => b }
}
def从对[A,B,
//定义具有类型参数并扩展FilterMonadic的类型C
C[X]
k->vlist.map{case(dupe,b)=>b}
}
编辑
注意,我使用了(A,B)
符号,而不是对[A,B]
这非常有用,感谢您向我介绍mapValues。它看起来与我在上面编写的map语句相同,忽略了键和列表值的映射。如果要将传递给mapValues的匿名函数改为命名函数,您将如何表示类型参数?这非常有用,感谢您向我介绍mapValues。它看起来相当于我上面写的map语句,忽略了键和列表值上的映射。如果您要编写作为命名函数传递给mapValues的匿名函数,您将如何表示类型参数?原因是(无可否认的混淆)诊断是要求C
获取对[a,B]
类型参数,然后引用C[B]
,这会导致编译器看到C[B]的参数位置中的形式B
(本身不是类型构造函数)和对B
的引用不一致
。如果这一点很清楚的话……C是一个正式的泛型参数,一个包含任何东西的泛型容器:`C[X]诊断的原因(无可否认是令人困惑的)是您需要C
获取一个对[a,B]
类型参数,然后参考C[B]
,这会导致编译器看到形式的B
(本身不是类型构造函数)和C[B]
的参数位置中对B
的引用之间不一致。如果这很清楚的话……C是一个形式的泛型参数,任何东西的泛型容器:`C[X]