-
Notifications
You must be signed in to change notification settings - Fork 130
/
Copy pathOrderedSet.swift
132 lines (108 loc) · 3.99 KB
/
OrderedSet.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
This source file is part of the Swift.org open source project
Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception
See http://swift.org/LICENSE.txt for license information
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
*/
/// An ordered set is an ordered collection of instances of `Element` in which
/// uniqueness of the objects is guaranteed.
public struct OrderedSet<E: Hashable>: Equatable, Collection {
public typealias Element = E
public typealias Index = Int
#if swift(>=4.1.50)
public typealias Indices = Range<Int>
#else
public typealias Indices = CountableRange<Int>
#endif
private var array: [Element]
private var set: Set<Element>
/// Creates an empty ordered set.
public init() {
self.array = []
self.set = Set()
}
/// Creates an ordered set with the contents of `array`.
///
/// If an element occurs more than once in `element`, only the first one
/// will be included.
public init(_ array: [Element]) {
self.init()
for element in array {
append(element)
}
}
// MARK: Working with an ordered set
/// The number of elements the ordered set stores.
public var count: Int { return array.count }
/// Returns `true` if the set is empty.
public var isEmpty: Bool { return array.isEmpty }
/// Returns the contents of the set as an array.
public var contents: [Element] { return array }
/// Returns `true` if the ordered set contains `member`.
public func contains(_ member: Element) -> Bool {
return set.contains(member)
}
/// Adds an element to the ordered set.
///
/// If it already contains the element, then the set is unchanged.
///
/// - returns: True if the item was inserted.
@discardableResult
public mutating func append(_ newElement: Element) -> Bool {
let inserted = set.insert(newElement).inserted
if inserted {
array.append(newElement)
}
return inserted
}
/// Remove and return the element at the beginning of the ordered set.
public mutating func removeFirst() -> Element {
let firstElement = array.removeFirst()
set.remove(firstElement)
return firstElement
}
/// Remove and return the element at the end of the ordered set.
public mutating func removeLast() -> Element {
let lastElement = array.removeLast()
set.remove(lastElement)
return lastElement
}
/// Remove all elements.
public mutating func removeAll(keepingCapacity keepCapacity: Bool) {
array.removeAll(keepingCapacity: keepCapacity)
set.removeAll(keepingCapacity: keepCapacity)
}
/// Remove the given element.
///
/// - returns: An element equal to member if member is contained in the set; otherwise, nil.
@discardableResult
public mutating func remove(_ element: Element) -> Element? {
let _removedElement = set.remove(element)
guard let removedElement = _removedElement else { return nil }
let idx = array.firstIndex(of: element)!
array.remove(at: idx)
return removedElement
}
}
extension OrderedSet: ExpressibleByArrayLiteral {
/// Create an instance initialized with `elements`.
///
/// If an element occurs more than once in `element`, only the first one
/// will be included.
public init(arrayLiteral elements: Element...) {
self.init(elements)
}
}
extension OrderedSet: RandomAccessCollection {
public var startIndex: Int { return contents.startIndex }
public var endIndex: Int { return contents.endIndex }
public subscript(index: Int) -> Element {
return contents[index]
}
}
public func == <T>(lhs: OrderedSet<T>, rhs: OrderedSet<T>) -> Bool {
return lhs.contents == rhs.contents
}
extension OrderedSet: Hashable where Element: Hashable { }
extension OrderedSet: Sendable where Element: Sendable { }