groupBy有一个术语可以返回多个组吗?

时间:2016-10-21 08:07:12

标签: scala haskell group-by functional-programming

groupBy的类型签名是(用scala语言,但实际上与语言无关):

def groupBy[K](f: A => K): Map[K, Seq[A]]

我实施了groupBy,返回多个K,以便每个A可以同时放入多个组。像这样:

def multiGroupBy[K](f: A => Seq[K]): Map[K, Seq[A]]

我做的事情如下:

case class Animal(name: String, traits: Seq[String])

List(
  Animal("cat", Seq("nocturnal", "feline")),
  Animal("dog", Seq("canine")),
  Animal("wolf", Seq("nocturnal", "canine"))
).multiGroupBy(animal => animal.traits)

// Map(nocturnal -> List(cat, wolf), feline -> List(cat), canine -> List(dog, wolf))

名称multiGroupBy有效,但我想知道是否已有一个术语(可能在haskell世界中?),如上所述。

1 个答案:

答案 0 :(得分:1)

如果您有Scalaz依赖关系,则可以使用foldMap执行此操作。

import scalaz._
import Scalaz._

case class Animal(name: String, traits: Seq[String])

val animals = List(
  Animal("cat", Seq("nocturnal", "feline")),
  Animal("dog", Seq("canine")),
  Animal("wolf", Seq("nocturnal", "canine"))
)

val r1 = animals.foldMap(a => a.traits.map(t => t -> List(a)).toMap)
println(r1)
// Map(nocturnal -> List(Animal(cat,List(nocturnal, feline)), Animal(wolf,List(nocturnal, canine))), feline -> List(Animal(cat,List(nocturnal, feline))), canine -> List(Animal(dog,List(canine)), Animal(wolf,List(nocturnal, canine))))

val r2 = animals.foldMap(a => a.traits.map(t => t -> List(a.name)).toMap)
println(r2)
// Map(nocturnal -> List(cat, wolf), feline -> List(cat), canine -> List(dog, wolf))

我们在这里做的是我们为动物列表中的每只动物创建了一个Map[String, List[Animal]],让Monoid[Map[String, List[Animal]]]合并每个地图。

例如Animal("cat", Seq("nocturnal", "feline"))变为Map("nocturnal" -> List(Animal("cat", Seq("nocturnal", "feline"))), "feline" -> List(Animal("cat", Seq("nocturnal", "feline"))))

关于幺半群的阅读:http://eed3si9n.com/learning-scalaz/Monoid.html