#scala #haskell #group-by #functional-programming
#scala #haskell #группировка по #функциональное программирование
Вопрос:
Подпись типа 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. Есть ли в вашем проекте зависимость от библиотеки функционального программирования, такая как
Scalaz
илиcats
? Если нет, вы не возражаете добавить одну? Потому что это можно решить с помощьюMonoid
иfoldMap
.2. @MustafaSimav Да, мой проект зависит от
Scalaz
!3. Не следует
multiGroupBy
возвращать aMap[K, Seq[A]]
и notMap[K, A]
?4. @TzachZohar Спасибо. Исправлено. На самом деле
groupBy
тоже пришлось вернутьMap[K, Seq[A]]
.
Ответ №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]]
для каждого животного в списке animals и позволили 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"))))
.
Для дальнейшего чтения о monoid: http://eed3si9n.com/learning-scalaz/Monoid.html
Комментарии:
1. Спасибо за ваш ответ. Но то, что я хотел знать, было не реализацией такой операции (я уже реализовал ее, используя аналогичную реализацию scala
groupBy
), а скорее уже существует метод для такой операции. Я почти уверен, что в scala std нет эквивалента, но мне было любопытно, существует ли общая терминология для этого в общем сообществе функционального программирования.2. Чтобы я мог назвать свой новый метод лучше, чем
multiGroupBy
😉