|
10 | 10 | //
|
11 | 11 | //===----------------------------------------------------------------------===//
|
12 | 12 |
|
13 |
| -/// Like a two-way dictionary |
| 13 | +/// Provides a bidirectional mapping between two keys. |
14 | 14 | ///
|
15 |
| -public struct BidirectionalMap<T1: Hashable, T2: Hashable>: Equatable, Sequence { |
| 15 | +/// `BidirectionalMap` provides efficient O(1) lookups in both directions. |
| 16 | +public struct BidirectionalMap<T1: Hashable, T2: Hashable>: Equatable { |
16 | 17 | private var map1: [T1: T2] = [:]
|
17 | 18 | private var map2: [T2: T1] = [:]
|
18 | 19 |
|
@@ -63,40 +64,53 @@ public struct BidirectionalMap<T1: Hashable, T2: Hashable>: Equatable, Sequence
|
63 | 64 | }
|
64 | 65 | }
|
65 | 66 | }
|
| 67 | +} |
66 | 68 |
|
67 |
| - public func contains(key: T1) -> Bool { |
68 |
| - map1.keys.contains(key) |
69 |
| - } |
70 |
| - public func contains(key: T2) -> Bool { |
71 |
| - map2.keys.contains(key) |
72 |
| - } |
73 |
| - |
| 69 | +extension BidirectionalMap { |
| 70 | + /// Updates the value stored in the bidirectional map for the given key, |
| 71 | + /// or adds a new set of key-value pairs if the key have an entry in the map. |
| 72 | + /// |
| 73 | + /// If access to the old value is not necessary, it is more efficient to use |
| 74 | + /// the subscript operator to perform an in-place update. |
| 75 | + /// |
| 76 | + /// - Parameters: |
| 77 | + /// - v: The new value to add to the two-level map. |
| 78 | + /// - key: The two-level key to associate with value. |
| 79 | + /// - Returns: The value that was replaced, or `nil` if a new key-value pair was added. |
| 80 | + @discardableResult |
74 | 81 | public mutating func updateValue(_ newValue: T2, forKey key: T1) -> T2? {
|
75 |
| - let oldValue = map1.updateValue(newValue, forKey: key) |
76 |
| - _ = oldValue.map {map2.removeValue(forKey: $0)} |
77 |
| - map2[newValue] = key |
78 |
| - return oldValue |
| 82 | + let old = self[key] |
| 83 | + self[key] = newValue |
| 84 | + return old |
79 | 85 | }
|
| 86 | + |
| 87 | + /// Updates the value stored in the bidirectional map for the given key, |
| 88 | + /// or adds a new set of key-value pairs if the key have an entry in the map. |
| 89 | + /// |
| 90 | + /// If access to the old value is not necessary, it is more efficient to use |
| 91 | + /// the subscript operator to perform an in-place update. |
| 92 | + /// |
| 93 | + /// - Parameters: |
| 94 | + /// - v: The new value to add to the two-level map. |
| 95 | + /// - key: The two-level key to associate with value. |
| 96 | + /// - Returns: The value that was replaced, or `nil` if a new key-value pair was added. |
| 97 | + @discardableResult |
80 | 98 | public mutating func updateValue(_ newValue: T1, forKey key: T2) -> T1? {
|
81 |
| - let oldValue = map2.updateValue(newValue, forKey: key) |
82 |
| - _ = oldValue.map {map1.removeValue(forKey: $0)} |
83 |
| - map1[newValue] = key |
84 |
| - return oldValue |
| 99 | + let old = self[key] |
| 100 | + self[key] = newValue |
| 101 | + return old |
85 | 102 | }
|
| 103 | +} |
86 | 104 |
|
87 |
| - public mutating func removeValue(forKey t1: T1) { |
88 |
| - if let t2 = map1[t1] { |
89 |
| - map2.removeValue(forKey: t2) |
90 |
| - } |
91 |
| - map1.removeValue(forKey: t1) |
92 |
| - } |
93 |
| - public mutating func removeValue(forKey t2: T2) { |
94 |
| - if let t1 = map2[t2] { |
95 |
| - map1.removeValue(forKey: t1) |
96 |
| - } |
97 |
| - map2.removeValue(forKey: t2) |
98 |
| - } |
| 105 | +extension BidirectionalMap: Sequence { |
| 106 | + /// Provides an iterator that yields pairs of the key-to-key mappings. |
| 107 | + /// |
| 108 | + /// - Warning: The order of the returned mappings is not stable. In general, |
| 109 | + /// avoid iterating over a bidirectional map unless order does not |
| 110 | + /// matter for the algorithm in question. |
| 111 | + /// |
| 112 | + /// - Returns: An iterator value for this bidirectional map. |
99 | 113 | public func makeIterator() -> Dictionary<T1, T2>.Iterator {
|
100 |
| - map1.makeIterator() |
| 114 | + self.map1.makeIterator() |
101 | 115 | }
|
102 | 116 | }
|
0 commit comments