From f51237583d0e0e0779dcffc7e471a2cabab359f1 Mon Sep 17 00:00:00 2001 From: James Bean Date: Wed, 12 Sep 2018 18:13:41 -0400 Subject: [PATCH] Add customized Bimap.filter, sprinkle in performance enhancements (#169) --- Sources/DataStructures/Bimap.swift | 33 ++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/Sources/DataStructures/Bimap.swift b/Sources/DataStructures/Bimap.swift index c68870e..c29630f 100644 --- a/Sources/DataStructures/Bimap.swift +++ b/Sources/DataStructures/Bimap.swift @@ -11,8 +11,11 @@ public struct Bimap : Hashable { // MARK: - Instance Properties - private var valueByKey: [Key: Value] - private var keyByValue: [Value: Key] + @usableFromInline + var valueByKey: [Key: Value] + + @usableFromInline + var keyByValue: [Value: Key] } extension Bimap { @@ -20,6 +23,7 @@ extension Bimap { // MARK: - Initializers /// Create an empty `Bimap`. + @inlinable public init() { self.valueByKey = [:] self.keyByValue = [:] @@ -27,24 +31,28 @@ extension Bimap { /// Create an empty `Bimap` reserving the amount of memory needed to store the given /// `minimumCapacity` of key-value pairs. + @inlinable public init(minimumCapacity: Int) { valueByKey = [Key: Value](minimumCapacity: minimumCapacity) keyByValue = [Value: Key](minimumCapacity: minimumCapacity) } /// Create a `Bimap` from a dictionary. + @inlinable public init(_ elements: Dictionary) { self.init(minimumCapacity: elements.count) for (k, value) in elements { self[key: k] = value } } /// Create a `Bimap` from the given `sequence` of key-value pairs. + @inlinable public init (_ sequence: S) where S.Element == (Key, Value) { self.init() for (k, value) in sequence { self[key: k] = value } } /// Create a `Bimap` from the given `collection` of key-value pairs. + @inlinable public init (_ collection: C) where C.Element == (Key, Value) { self.init(minimumCapacity: collection.count) for (k, value) in collection { self[key: k] = value } @@ -56,21 +64,25 @@ extension Bimap { // MARK: - Computed Properties /// - Returns: The amount of key-value pairs contained herein. + @inlinable public var count: Int { return valueByKey.count } /// - Returns: `true` if there are no key-value pairs contained herein. Otherwise, `false`. + @inlinable public var isEmpty: Bool { return valueByKey.isEmpty } /// - Returns: A collection of `Key` values. + @inlinable public var keys: AnyCollection { return AnyCollection(valueByKey.keys) } /// - Returns: A collection of `Value` values. + @inlinable public var values: AnyCollection { return AnyCollection(keyByValue.keys) } @@ -81,6 +93,7 @@ extension Bimap { // MARK: - Subscripts /// Get and set the `Key` for the given `value`. + @inlinable public subscript(value value: Value) -> Key? { get { return keyByValue[value] } set(newKey) { @@ -92,6 +105,7 @@ extension Bimap { } /// Get and set the `Value` for the given `key`. + @inlinable public subscript(key key: Key) -> Value? { get { return valueByKey[key] } set { @@ -110,6 +124,7 @@ extension Bimap { /// Updates the current value to the given `value` for the given `key`. /// /// - Returns: The previous value for the given `key`, if it existed. Otherwise, `nil`. + @inlinable @discardableResult public mutating func updateValue(_ value: Value, forKey key: Key) -> Value? { let previous = self[key: key] @@ -120,6 +135,7 @@ extension Bimap { /// Updates the current key to the given `key` for the given `value`. /// /// - Returns: The previous key for the given `value`, if it existed. Otherwise, `nil`. + @inlinable @discardableResult public mutating func updateKey(_ key: Key, forValue value: Value) -> Key? { let previous = self[value: value] @@ -130,6 +146,7 @@ extension Bimap { /// Removes the value for the given `key`. /// /// - Returns: The previous value for the given `key`, if it existed. Otherwise, `nil`. + @inlinable @discardableResult public mutating func removeValue(forKey key: Key) -> Value? { let previous = self[key: key] @@ -140,6 +157,7 @@ extension Bimap { /// Removes the key for the given `value`. /// /// - Returns: The previous key for the given `value`, if it existed. Otherwise, `nil`. + @inlinable @discardableResult public mutating func removeKey(forValue value: Value) -> Key? { let previous = self[value: value] @@ -148,15 +166,23 @@ extension Bimap { } /// Removes all key-value pairs, without releasing memory. + @inlinable public mutating func removeAll(keepCapacity capacity: Bool = true) { keyByValue.removeAll(keepingCapacity: capacity) valueByKey.removeAll(keepingCapacity: capacity) } + + /// - Returns: A `Bimap` with the keys and values filtered by the given `isIncluded`. + @inlinable + public func filter(_ isIncluded: ((key: Key, value: Value)) throws -> Bool) rethrows -> Bimap { + return try Bimap(base.lazy.filter(isIncluded)) + } } extension Bimap: DictionaryProtocol { /// Gets and sets the value for the `key`. + @inlinable public subscript(key: Key) -> Value? { get { return self[key: key] } set { self[key: key] = newValue } @@ -164,6 +190,7 @@ extension Bimap: DictionaryProtocol { /// Reserves the amount of memory needed to store the given `minimumCapacity` of key-value /// pairs. + @inlinable public mutating func reserveCapacity(_ minimumCapacity: Int) { valueByKey.reserveCapacity(minimumCapacity) keyByValue.reserveCapacity(minimumCapacity) @@ -175,6 +202,7 @@ extension Bimap: CollectionWrapping { // MARK: - CollectionWrapping /// - Returns: The `[Key: Value]` base for `Collection` operations. + @inlinable public var base: [Key: Value] { return valueByKey } @@ -184,6 +212,7 @@ extension Bimap: ExpressibleByDictionaryLiteral { // MARK: ExpressibleByDictionaryLiteral Protocol Conformance /// Constructs a bimap using a dictionary literal. + @inlinable public init(dictionaryLiteral elements: (Key, Value)...) { self.init(elements) }