Advertisement
Guest User

Untitled

a guest
Mar 18th, 2019
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.33 KB | None | 0 0
  1. package java2scala.homeworks
  2.  
  3. sealed trait LinkedMap[K, V] extends Traversable[(K, V)] {
  4.  
  5. /** должен вернуть `false` если коллекция содержит хотя бы один элемент */
  6. override def isEmpty: Boolean = this match {
  7. case LinkedMap.Empty() => true
  8. case _ => false
  9. }
  10.  
  11. /** должен вернуть `true` если коллекция содержит ключ `key` */
  12. def contains(key: K): Boolean = this match {
  13. case LinkedMap.Empty() => false
  14. case LinkedMap.Cons(k, _, rest) =>
  15. if (k == key) true
  16. else rest.contains(key)
  17. }
  18.  
  19. /** возвращает Some со значением значения, если коллекция содержит ключ `key`
  20. * и None если не содержит */
  21. def apply(key: K): Option[V] = this match {
  22. case LinkedMap.Empty() => None
  23. case LinkedMap.Cons(k, v, rest) =>
  24. if (k == key) Some(v)
  25. else rest.apply(key)
  26. }
  27.  
  28. /** возвращает новый LinkedMap[K, V],
  29. * в котором добавлено или изменено значение для ключа `key` на `value` */
  30. def update(key: K, value: V): LinkedMap[K, V] = {
  31. def go(lm: LinkedMap[K, V], acc: LinkedMap[K, V]): LinkedMap[K, V] = lm match {
  32. case LinkedMap.Empty() => acc.reverse
  33. case LinkedMap.Cons(k, v, rest) =>
  34. if (k == key) go(rest, LinkedMap.Cons(k, value, acc))
  35. else go(rest, LinkedMap.Cons(k, v, acc))
  36. }
  37.  
  38. if (this.contains(key)) go(this, LinkedMap.Empty())
  39. else LinkedMap.Cons(key, value, this)
  40. }
  41.  
  42. /** возвращает новый LinkedMap[K, V]
  43. * состоящий из тех же позиций, но в обратном порядке */
  44. def reverse: LinkedMap[K, V] = {
  45. def go(lm: LinkedMap[K, V], acc: LinkedMap[K, V]): LinkedMap[K, V] = lm match {
  46. case LinkedMap.Empty() => acc
  47. case LinkedMap.Cons(k, v, rest) => go(rest, LinkedMap.Cons(k, v, acc))
  48. }
  49.  
  50. go(this, LinkedMap.Empty())
  51. }
  52.  
  53. /** создаёт новый LinkedMap, состоящий из элементов `this` и `other`
  54. * если какой-то ключ встречается в обеих коллекциях,
  55. * может быть выбрано любое значение*/
  56. def ++(other: LinkedMap[K, V]): LinkedMap[K, V] = {
  57. def go(lml: LinkedMap[K, V], lmr: LinkedMap[K, V]): LinkedMap[K, V] = lml match {
  58. case LinkedMap.Empty() => lmr
  59. case LinkedMap.Cons(k, v, rest) =>
  60. if (lmr.contains(k)) go(rest, lmr)
  61. else go(rest, LinkedMap.Cons(k, v, lmr))
  62. }
  63.  
  64. go(this, other)
  65. }
  66.  
  67. /** создаёт новый LinkedMap , где ко всем значениям применена заданная функция */
  68. def mapValues[W](f: V => W): LinkedMap[K, W] = {
  69. def go(lm: LinkedMap[K, V], acc: LinkedMap[K, W]): LinkedMap[K, W] = lm match {
  70. case LinkedMap.Empty() => acc.reverse
  71. case LinkedMap.Cons(k, v, rest) => go(rest, LinkedMap.Cons(k, f(v), acc))
  72. }
  73.  
  74. go(this, LinkedMap.Empty())
  75. }
  76.  
  77. /** создаёт новый LinkedMap , где ко всем значениям применена заданная функция,
  78. * учитывающая ключ*/
  79. def mapWithKey[W](f: (K, V) => W): LinkedMap[K, W] = {
  80. def go(lm: LinkedMap[K, V], acc: LinkedMap[K, W]): LinkedMap[K, W] = lm match {
  81. case LinkedMap.Empty() => acc.reverse
  82. case LinkedMap.Cons(k, v, rest) => go(rest, LinkedMap.Cons(k, f(k, v), acc))
  83. }
  84.  
  85. go(this, LinkedMap.Empty())
  86. }
  87.  
  88. /** конструирует новый LinkedMap, содеоржащий все записи текущего, кроме заданного ключа */
  89. def delete(key: K): LinkedMap[K, V] = {
  90. def go(lm: LinkedMap[K, V], acc: LinkedMap[K, V]): LinkedMap[K, V] = lm match {
  91. case LinkedMap.Empty() => acc.reverse
  92. case LinkedMap.Cons(k, v, rest) =>
  93. if (k == key) go(rest, acc)
  94. else go(rest, LinkedMap.Cons(k, v, acc))
  95. }
  96.  
  97. go(this, LinkedMap.Empty())
  98. }
  99.  
  100. /** применяет действие `action` с побочным эффектом ко всем элементам коллекции */
  101. def foreach[U](action: ((K, V)) => U): Unit = this match {
  102. case LinkedMap.Empty() => ()
  103. case LinkedMap.Cons(k, v, rest) =>
  104. action(k, v)
  105. rest.foreach(action)
  106. }
  107. }
  108.  
  109. object LinkedMap {
  110.  
  111. /** конструирует новый `LinkedMap` на основании приведённых элементов
  112. * каждый ключ должен присутствовать в результате только один раз
  113. * если в исходных данныхх ключ встречается несколько раз, может быть
  114. * выбрано любое из значений
  115. */
  116. def apply[K, V](kvs: (K, V)*): LinkedMap[K, V] = {
  117. def go(KVSeq: Seq[(K, V)], acc: LinkedMap[K, V]): LinkedMap[K, V] = KVSeq match {
  118. case Seq() => acc
  119. case (k, v) +: tail =>
  120. if (acc.contains(k)) go(tail, acc)
  121. else go(tail, LinkedMap.Cons(k, v, acc))
  122. }
  123.  
  124. go(kvs, Empty())
  125. }
  126.  
  127. final case class Cons[K, V](key: K, value: V, rest: LinkedMap[K, V]) extends LinkedMap[K, V]
  128. final case class Empty[K, V]() extends LinkedMap[K, V]
  129. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement