如何在Scala中编写此递归groupBy函数
最近,我遇到了Groovy在Iterable上提供的一个非常有用的groupBy函数:如何在Scala中编写此递归groupBy函数,scala,recursion,types,Scala,Recursion,Types,最近,我遇到了Groovy在Iterable上提供的一个非常有用的groupBy函数: public static Map groupBy(Iterable self, List<Closure> closures) 另外,我如何用正确的类型实现递归 这是一个简单的多组实现: implicit class GroupOps[A](coll: Seq[A]) { def groupByKeys[B](fs: (A => B)*): Map[Seq[B], Seq[A]] =
public static Map groupBy(Iterable self, List<Closure> closures)
另外,我如何用正确的类型实现递归 这是一个简单的多组实现:
implicit class GroupOps[A](coll: Seq[A]) {
def groupByKeys[B](fs: (A => B)*): Map[Seq[B], Seq[A]] =
coll.groupBy(elem => fs map (_(elem)))
}
val a = 1 to 20
a.groupByKeys(_ % 3, _ % 2) foreach println
如果您确实需要某种递归类型,则需要一个包装器:
sealed trait RecMap[K, V]
case class MapUnit[K, V](elem: V) extends RecMap[K, V] {
override def toString = elem.toString()
}
case class MapLayer[K, V](map: Map[K, RecMap[K, V]]) extends RecMap[K, V] {
override def toString = map.toString()
}
将定义更改为:
implicit class GroupOps[A](coll: Seq[A]) {
def groupByKeys[B](fs: (A => B)*): Map[Seq[B], Seq[A]] =
coll.groupBy(elem => fs map (_(elem)))
def groupRecursive[B](fs: (A => B)*): RecMap[B, Seq[A]] = fs match {
case Seq() => MapUnit(coll)
case f +: fs => MapLayer(coll groupBy f mapValues {_.groupRecursive(fs: _*)})
}
}
而a.groupRecursive%3,%2产生了与问题更相关的东西
最后,我根据参考文章重建域定义:
case class User(name: String, city: String, birthDate: Date) {
override def toString = name
}
implicit val date = new SimpleDateFormat("yyyy-MM-dd").parse(_: String)
val month = new SimpleDateFormat("MMM").format (_:Date)
val users = List(
User(name = "mrhaki", city = "Tilburg" , birthDate = "1973-9-7"),
User(name = "bob" , city = "New York" , birthDate = "1963-3-30"),
User(name = "britt" , city = "Amsterdam", birthDate = "1980-5-12"),
User(name = "kim" , city = "Amsterdam", birthDate = "1983-3-30"),
User(name = "liam" , city = "Tilburg" , birthDate = "2009-3-6")
)
现在我们可以写作了
users.groupRecursive(_.city, u => month(u.birthDate))
得到
MapTilburg->MapMar->Listliam,九月->Listmrhaki,纽约
->MapMar->Listbob,阿姆斯特丹->MapMar->Listkim,May->Listbritt
这是一个简单的多组实现:
implicit class GroupOps[A](coll: Seq[A]) {
def groupByKeys[B](fs: (A => B)*): Map[Seq[B], Seq[A]] =
coll.groupBy(elem => fs map (_(elem)))
}
val a = 1 to 20
a.groupByKeys(_ % 3, _ % 2) foreach println
如果您确实需要某种递归类型,则需要一个包装器:
sealed trait RecMap[K, V]
case class MapUnit[K, V](elem: V) extends RecMap[K, V] {
override def toString = elem.toString()
}
case class MapLayer[K, V](map: Map[K, RecMap[K, V]]) extends RecMap[K, V] {
override def toString = map.toString()
}
将定义更改为:
implicit class GroupOps[A](coll: Seq[A]) {
def groupByKeys[B](fs: (A => B)*): Map[Seq[B], Seq[A]] =
coll.groupBy(elem => fs map (_(elem)))
def groupRecursive[B](fs: (A => B)*): RecMap[B, Seq[A]] = fs match {
case Seq() => MapUnit(coll)
case f +: fs => MapLayer(coll groupBy f mapValues {_.groupRecursive(fs: _*)})
}
}
而a.groupRecursive%3,%2产生了与问题更相关的东西
最后,我根据参考文章重建域定义:
case class User(name: String, city: String, birthDate: Date) {
override def toString = name
}
implicit val date = new SimpleDateFormat("yyyy-MM-dd").parse(_: String)
val month = new SimpleDateFormat("MMM").format (_:Date)
val users = List(
User(name = "mrhaki", city = "Tilburg" , birthDate = "1973-9-7"),
User(name = "bob" , city = "New York" , birthDate = "1963-3-30"),
User(name = "britt" , city = "Amsterdam", birthDate = "1980-5-12"),
User(name = "kim" , city = "Amsterdam", birthDate = "1983-3-30"),
User(name = "liam" , city = "Tilburg" , birthDate = "2009-3-6")
)
现在我们可以写作了
users.groupRecursive(_.city, u => month(u.birthDate))
得到
MapTilburg->MapMar->Listliam,九月->Listmrhaki,纽约
->MapMar->Listbob,阿姆斯特丹->MapMar->Listkim,May->Listbritt
由于方法完全不同,我决定添加另一个答案 实际上,您可以使用大量变通方法获得非包装的正确类型的地图。我不太擅长这个,所以碰巧可以简化一下 诀窍是创建类型化函数序列,该序列最近使用类型类和类型路径方法生成多级映射 这就是解决方案
sealed trait KeySeq[-V] {
type values
}
case class KeyNil[V]() extends KeySeq[V] {
type values = Seq[V]
}
case class KeyCons[K, V, Next <: KeySeq[V]](f: V => K, next: Next)
(implicit ev: RecGroup[V, Next]) extends KeySeq[V] {
type values = Map[K, Next#values]
def #:[K1](f: V => K1) = new KeyCons[K1, V, KeyCons[K, V, Next]](f, this)
}
trait RecGroup[V, KS <: KeySeq[V]] {
def group(seq: Seq[V], ks: KS): KS#values
}
implicit def groupNil[V]: RecGroup[V, KeyNil[V]] = new RecGroup[V, KeyNil[V]] {
def group(seq: Seq[V], ks: KeyNil[V]) = seq
}
implicit def groupCons[K, V, Next <: KeySeq[V]](implicit ev: RecGroup[V, Next]): RecGroup[V, KeyCons[K, V, Next]] =
new RecGroup[V, KeyCons[K, V, Next]] {
def group(seq: Seq[V], ks: KeyCons[K, V, Next]) = seq.groupBy(ks.f) mapValues (_ groupRecursive ks.next)
}
implicit def funcAsKey[K, V](f: V => K): KeyCons[K, V, KeyNil[V]] =
new KeyCons[K, V, KeyNil[V]](f, KeyNil[V]())
implicit class GroupOps[V](coll: Seq[V]) {
def groupRecursive[KS <: KeySeq[V]](ks: KS)(implicit g: RecGroup[V, KS]) =
g.group(coll, ks)
}
然后
将产生正确的映射[布尔,映射[Int,映射[Int,Int]]
如果从前面的问题我们想
users.groupRecursive(((u:User)=> u.city(0)) #: ((u:User) => month(u.birthDate)))
我们正在构建Map[Char,Map[String,User] 由于方法完全不同,我决定添加另一个答案 实际上,您可以使用大量变通方法获得非包装的正确类型的地图。我不太擅长这个,所以碰巧可以简化一下 诀窍是创建类型化函数序列,该序列最近使用类型类和类型路径方法生成多级映射 这就是解决方案
sealed trait KeySeq[-V] {
type values
}
case class KeyNil[V]() extends KeySeq[V] {
type values = Seq[V]
}
case class KeyCons[K, V, Next <: KeySeq[V]](f: V => K, next: Next)
(implicit ev: RecGroup[V, Next]) extends KeySeq[V] {
type values = Map[K, Next#values]
def #:[K1](f: V => K1) = new KeyCons[K1, V, KeyCons[K, V, Next]](f, this)
}
trait RecGroup[V, KS <: KeySeq[V]] {
def group(seq: Seq[V], ks: KS): KS#values
}
implicit def groupNil[V]: RecGroup[V, KeyNil[V]] = new RecGroup[V, KeyNil[V]] {
def group(seq: Seq[V], ks: KeyNil[V]) = seq
}
implicit def groupCons[K, V, Next <: KeySeq[V]](implicit ev: RecGroup[V, Next]): RecGroup[V, KeyCons[K, V, Next]] =
new RecGroup[V, KeyCons[K, V, Next]] {
def group(seq: Seq[V], ks: KeyCons[K, V, Next]) = seq.groupBy(ks.f) mapValues (_ groupRecursive ks.next)
}
implicit def funcAsKey[K, V](f: V => K): KeyCons[K, V, KeyNil[V]] =
new KeyCons[K, V, KeyNil[V]](f, KeyNil[V]())
implicit class GroupOps[V](coll: Seq[V]) {
def groupRecursive[KS <: KeySeq[V]](ks: KS)(implicit g: RecGroup[V, KS]) =
g.group(coll, ks)
}
然后
将产生正确的映射[布尔,映射[Int,映射[Int,Int]]
如果从前面的问题我们想
users.groupRecursive(((u:User)=> u.city(0)) #: ((u:User) => month(u.birthDate)))
我们正在构建Map[Char,Map[String,User] 太棒了!不知道递归类型。非常感谢,太棒了!不知道递归类型。非常感谢。