Created
January 23, 2024 18:58
-
-
Save ivanopcode/376957326dd9ad87bcb28211d5781c9d to your computer and use it in GitHub Desktop.
Swift OrderedStrictidSet data structure draft
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// MIT License | |
// | |
// Copyright (c) 2024 Ivan Oparin | |
// | |
// Permission is hereby granted, free of charge, to any person obtaining a copy | |
// of this software and associated documentation files (the "Software"), to deal | |
// in the Software without restriction, including without limitation the rights | |
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
// copies of the Software, and to permit persons to whom the Software is | |
// furnished to do so, subject to the following conditions: | |
// | |
// The above copyright notice and this permission notice shall be included in all | |
// copies or substantial portions of the Software. | |
// | |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
// SOFTWARE. | |
/// An ordered collection of elements with unique identities. | |
/// | |
/// Use an OrderedStrictidSet when you need to maintain not only the uniqueness | |
/// of elements based on their explicit identity but also their insertion order. | |
/// This is ideal in scenarios where the sequence in which elements are added | |
/// matters, yet each element has a stable, unique identifier that must be | |
/// preserved. OrderedStrictidSet ensures that, despite any changes in an | |
/// element's properties, its identity (as defined by its id property) dictates | |
/// its continued presence and position in the set. | |
/// | |
/// You can create an OrderedStrictidSet with any element type that conforms to | |
/// the Identifiable protocol. This makes OrderedStrictidSet suitable for | |
/// storing complex objects where both identity and order are significant, | |
/// beyond the object's current state or value. | |
/// | |
/// ```swift | |
/// struct Document: Identifiable { | |
/// let id: Int | |
/// var title: String | |
/// } | |
/// | |
/// var documents: OrderedStrictidSet = [Document(id: 1, title: "Report"), | |
/// Document(id: 2, title: "Summary")] | |
/// let updatedDocument = Document(id: 1, title: "Updated Report") | |
/// documents.update(with: updatedDocument) | |
/// | |
/// // The 'documents' set maintains the updated Document and its order | |
/// ``` | |
/// | |
/// Identity-Based Ordered Set Operations | |
/// ====================================== | |
/// | |
/// OrderedStrictidSet provides operations similar to a standard set, but with | |
/// the added feature of maintaining the order of elements. These operations | |
/// are based on the identity of elements rather than their hash values: | |
/// | |
/// - Use the contains(_:) method to check whether the set contains an | |
/// element with a specific identifier. | |
/// - Use the update(with:) method to replace an existing element with a new | |
/// one, maintaining its original position, as long as they share the same | |
/// identifier. | |
/// - Use the remove(_:) method to remove an element based on its identifier | |
/// without disrupting the order of other elements. | |
/// | |
/// The operations in OrderedStrictidSet ensure that the order of elements | |
/// is preserved, aligning with the initial insertion sequence, irrespective | |
/// of any changes in the properties of the elements. | |
/// ```swift | |
/// var projects: OrderedStrictidSet = [Project(id: 1, status: "Starting"), | |
/// Project(id: 2, status: "In Progress")] | |
/// let updatedProject = Project(id: 1, status: "Completed") | |
/// projects.update(with: updatedProject) | |
/// // The 'projects' set now maintains the updated Project 1 in its original | |
/// // position and the Project 2 | |
/// ``` | |
/// Preserving Order and Unique Identities | |
/// ====================================== | |
/// | |
/// OrderedStrictidSet is especially useful in contexts where both the order | |
/// and the integrity of each element, based on a stable identity, are crucial. | |
/// This includes applications like task management, playlist curation, or | |
/// document revision tracking, where the order of elements carries | |
/// significant meaning. | |
/// | |
/// ```swift | |
/// for document in documents { | |
/// print("Document ID: \(document.id), Title: \(document.title)") | |
/// } | |
/// // Prints "Document ID: 1, Title: Updated Report" | |
/// // Prints "Document ID: 2, Title: Summary" | |
/// ``` | |
/// | |
/// Unlike standard ordered collections, OrderedStrictidSet does not depend | |
/// on hash values for order and uniqueness checks, making it an effective | |
/// choice for scenarios where an object's identity and its sequence in a | |
/// collection are both of paramount importance. | |
struct StrictidSet<Element: Identifiable> { | |
private var _elements: OrderedDictionary<Element.ID, Element> = [:] | |
var count: Int { | |
_elements.count | |
} | |
var isEmpty: Bool { | |
_elements.isEmpty | |
} | |
var elements: [Element] { | |
Array(_elements.values) | |
} | |
@discardableResult | |
mutating func insert(_ element: Element) -> (inserted: Bool, memberAfterInsert: Element) { | |
if _elements.keys.contains(element.id) { | |
return (false, _elements[element.id]!) | |
} else { | |
_elements[element.id] = element | |
return (true, element) | |
} | |
} | |
@discardableResult | |
mutating func update(with newMember: Element) -> Element? { | |
let oldMember = _elements[newMember.id] | |
_elements[newMember.id] = newMember | |
return oldMember | |
} | |
@discardableResult | |
mutating func remove(_ member: Element) -> Element? { | |
return _elements.removeValue(forKey: member.id) | |
} | |
func contains(_ element: Element) -> Bool { | |
_elements.keys.contains(element.id) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment