Refine UnorderedSparseSet

This commit is contained in:
Christian Treffs 2020-07-09 17:10:00 +02:00
parent d30a3bec3b
commit 63c09cf7fa
No known key found for this signature in database
GPG Key ID: 49A4B4B460BE3ED4
1 changed files with 33 additions and 18 deletions

View File

@ -5,23 +5,36 @@
// Created by Christian Treffs on 30.10.17. // Created by Christian Treffs on 30.10.17.
// //
public struct UnorderedSparseSet<Element> { /// An (unordered) sparse set.
public typealias Index = Int ///
public typealias Key = Int /// - `Element`: the element (instance) to store.
/// - `Key`: the unique, hashable datastructure to use as a key to retrieve
/// an element from the sparse set.
///
/// See <https://github.com/bombela/sparseset/blob/master/src/lib.rs> for a reference implementation.
public struct UnorderedSparseSet<Element, Key: Hashable & Codable> {
/// An index into the dense store.
public typealias DenseIndex = Int
/// A sparse store holding indices into the dense mapped to key.
public typealias SparseStore = [Key: DenseIndex]
/// A dense store holding all the entries.
public typealias DenseStore = ContiguousArray<Entry>
public struct Entry { public struct Entry {
public let key: Key public let key: Key
public let element: Element public let element: Element
} }
@usableFromInline var dense: ContiguousArray<Entry> @usableFromInline var dense: DenseStore
@usableFromInline var sparse: [Key: Index] @usableFromInline var sparse: SparseStore
public init() { public init() {
self.init(sparse: [:], dense: []) self.init(sparse: [:], dense: [])
} }
init(sparse: [Index: Key], dense: ContiguousArray<Entry>) { init(sparse: SparseStore, dense: DenseStore) {
self.sparse = sparse self.sparse = sparse
self.dense = dense self.dense = dense
} }
@ -120,8 +133,18 @@ public struct UnorderedSparseSet<Element> {
return (denseIndex, entry.element) return (denseIndex, entry.element)
} }
@inlinable public var first: Element? {
dense.first?.element
}
@inlinable public var last: Element? {
dense.last?.element
}
}
extension UnorderedSparseSet where Key == Int {
@inlinable @inlinable
public subscript(position: Index) -> Element { public subscript(position: DenseIndex) -> Element {
get { get {
get(unsafeAt: position) get(unsafeAt: position)
} }
@ -130,14 +153,6 @@ public struct UnorderedSparseSet<Element> {
insert(newValue, at: position) insert(newValue, at: position)
} }
} }
@inlinable public var first: Element? {
dense.first?.element
}
@inlinable public var last: Element? {
dense.last?.element
}
} }
// MARK: - Sequence // MARK: - Sequence
@ -148,9 +163,9 @@ extension UnorderedSparseSet: Sequence {
// MARK: - UnorderedSparseSetIterator // MARK: - UnorderedSparseSetIterator
public struct ElementIterator: IteratorProtocol { public struct ElementIterator: IteratorProtocol {
public private(set) var iterator: IndexingIterator<ContiguousArray<UnorderedSparseSet<Element>.Entry>> public private(set) var iterator: IndexingIterator<ContiguousArray<UnorderedSparseSet<Element, Key>.Entry>>
public init(_ sparseSet: UnorderedSparseSet<Element>) { public init(_ sparseSet: UnorderedSparseSet<Element, Key>) {
iterator = sparseSet.dense.makeIterator() iterator = sparseSet.dense.makeIterator()
} }
@ -163,7 +178,7 @@ extension UnorderedSparseSet: Sequence {
// MARK: - Equatable // MARK: - Equatable
extension UnorderedSparseSet.Entry: Equatable where Element: Equatable { } extension UnorderedSparseSet.Entry: Equatable where Element: Equatable { }
extension UnorderedSparseSet: Equatable where Element: Equatable { extension UnorderedSparseSet: Equatable where Element: Equatable {
public static func == (lhs: UnorderedSparseSet<Element>, rhs: UnorderedSparseSet<Element>) -> Bool { public static func == (lhs: UnorderedSparseSet<Element, Key>, rhs: UnorderedSparseSet<Element, Key>) -> Bool {
lhs.dense == rhs.dense && lhs.sparse == rhs.sparse lhs.dense == rhs.dense && lhs.sparse == rhs.sparse
} }
} }