| author | paulson | 
| Mon, 08 Nov 2021 09:31:26 +0000 | |
| changeset 74730 | 25f5f1fa31bb | 
| parent 73362 | dde25151c3c1 | 
| child 75393 | 87ebf5a50283 | 
| permissions | -rw-r--r-- | 
| 52975 | 1 | /* Title: Pure/General/multi_map.scala | 
| 56744 | 2 | Author: Makarius | 
| 52975 | 3 | |
| 4 | Maps with multiple entries per key. | |
| 5 | */ | |
| 6 | ||
| 7 | package isabelle | |
| 8 | ||
| 73136 | 9 | import scala.collection.mutable | 
| 10 | import scala.collection.{IterableFactory, MapFactory, MapFactoryDefaults}
 | |
| 11 | import scala.collection.immutable.{Iterable, MapOps}
 | |
| 52975 | 12 | |
| 13 | ||
| 73136 | 14 | object Multi_Map extends MapFactory[Multi_Map] | 
| 52975 | 15 | {
 | 
| 16 | private val empty_val: Multi_Map[Any, Nothing] = new Multi_Map[Any, Nothing](Map.empty) | |
| 73136 | 17 | def empty[A, B]: Multi_Map[A, B] = empty_val.asInstanceOf[Multi_Map[A, B]] | 
| 18 | ||
| 19 | def from[A, B](entries: IterableOnce[(A, B)]): Multi_Map[A, B] = | |
| 73362 | 20 |     entries.iterator.foldLeft(empty[A, B]) { case (m, (a, b)) => m.insert(a, b) }
 | 
| 52975 | 21 | |
| 73136 | 22 | override def newBuilder[A, B]: mutable.Builder[(A, B), Multi_Map[A, B]] = new Builder[A, B] | 
| 23 | private class Builder[A, B] extends mutable.Builder[(A, B), Multi_Map[A, B]] | |
| 24 |   {
 | |
| 25 | private var res = empty[A, B] | |
| 73340 | 26 |     override def clear(): Unit = { res = empty[A, B] }
 | 
| 73136 | 27 |     override def addOne(p: (A, B)): this.type = { res = res.insert(p._1, p._2); this }
 | 
| 28 | override def result(): Multi_Map[A, B] = res | |
| 29 | } | |
| 52975 | 30 | } | 
| 31 | ||
| 59073 | 32 | final class Multi_Map[A, +B] private(protected val rep: Map[A, List[B]]) | 
| 73136 | 33 | extends Iterable[(A, B)] | 
| 34 | with MapOps[A, B, Multi_Map, Multi_Map[A, B]] | |
| 35 | with MapFactoryDefaults[A, B, Multi_Map, Iterable] | |
| 52975 | 36 | {
 | 
| 37 | /* Multi_Map operations */ | |
| 38 | ||
| 55488 
60c159d490a2
more integrity checks of theory names vs. full node names;
 wenzelm parents: 
52975diff
changeset | 39 | def iterator_list: Iterator[(A, List[B])] = rep.iterator | 
| 
60c159d490a2
more integrity checks of theory names vs. full node names;
 wenzelm parents: 
52975diff
changeset | 40 | |
| 52975 | 41 | def get_list(a: A): List[B] = rep.getOrElse(a, Nil) | 
| 42 | ||
| 43 | def insert[B1 >: B](a: A, b: B1): Multi_Map[A, B1] = | |
| 44 |   {
 | |
| 45 | val bs = get_list(a) | |
| 46 | if (bs.contains(b)) this | |
| 47 | else new Multi_Map(rep + (a -> (b :: bs))) | |
| 48 | } | |
| 49 | ||
| 50 | def remove[B1 >: B](a: A, b: B1): Multi_Map[A, B1] = | |
| 51 |   {
 | |
| 52 | val bs = get_list(a) | |
| 53 |     if (bs.contains(b)) {
 | |
| 54 |       bs.filterNot(_ == b) match {
 | |
| 55 | case Nil => new Multi_Map(rep - a) | |
| 56 | case bs1 => new Multi_Map(rep + (a -> bs1)) | |
| 57 | } | |
| 58 | } | |
| 59 | else this | |
| 60 | } | |
| 61 | ||
| 59073 | 62 | def ++[B1 >: B] (other: Multi_Map[A, B1]): Multi_Map[A, B1] = | 
| 63 | if (this eq other) this | |
| 64 | else if (isEmpty) other | |
| 65 | else | |
| 73359 | 66 |       other.rep.iterator.foldLeft(this.asInstanceOf[Multi_Map[A, B1]]) {
 | 
| 73360 | 67 |         case (m1, (a, bs)) => bs.foldRight(m1) { case (b, m2) => m2.insert(a, b) }
 | 
| 59073 | 68 | } | 
| 69 | ||
| 52975 | 70 | |
| 71 | /* Map operations */ | |
| 72 | ||
| 71601 | 73 | override def empty: Multi_Map[A, Nothing] = Multi_Map.empty | 
| 52975 | 74 | override def isEmpty: Boolean = rep.isEmpty | 
| 75 | ||
| 76 | override def keySet: Set[A] = rep.keySet | |
| 77 | ||
| 78 | override def iterator: Iterator[(A, B)] = | |
| 79 | for ((a, bs) <- rep.iterator; b <- bs.iterator) yield (a, b) | |
| 80 | ||
| 81 | def get(a: A): Option[B] = get_list(a).headOption | |
| 82 | ||
| 73136 | 83 | override def updated[B1 >: B](a: A, b: B1): Multi_Map[A, B1] = insert(a, b) | 
| 84 | ||
| 85 | override def removed(a: A): Multi_Map[A, B] = | |
| 86 | if (rep.isDefinedAt(a)) new Multi_Map(rep - a) else this | |
| 52975 | 87 | |
| 73136 | 88 | override def mapFactory: MapFactory[Multi_Map] = Multi_Map | 
| 63579 | 89 | |
| 73136 | 90 |   override def toString: String = mkString("Multi_Map(", ", ", ")")
 | 
| 52975 | 91 | } |