Skip to content

Instantly share code, notes, and snippets.

@tempire
Created November 12, 2016 19:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tempire/852ea4d1c8420a033ccb966f6cc8b696 to your computer and use it in GitHub Desktop.
Save tempire/852ea4d1c8420a033ccb966f6cc8b696 to your computer and use it in GitHub Desktop.
Swift 2.2-2.3 Custom collection
// From Ray Wenderlich, converted to swift 2
extension Structs: CustomStringConvertible {
var description: String {
return contents.description
}
}
extension Structs: ArrayLiteralConvertible {
init(arrayLiteral elements: Element...) {
self.init(elements)
}
}
extension Structs: DictionaryLiteralConvertible {
init(dictionaryLiteral elements: (Element, Int)...) {
self.init(elements.map { (key: $0.0, value: $0.1) } )
}
}
extension Structs: SequenceType {
typealias Generator = AnyGenerator<(element: Element, count: Int)>
func generate() -> Structs.Generator {
var generator = contents.generate()
return AnyGenerator {
return generator.next()
}
}
}
extension Structs: CollectionType {
typealias Index = DictionaryIndex<Element, Int>
var startIndex: Index {
return contents.startIndex
}
var endIndex: Index {
return contents.endIndex
}
subscript(position: Index) -> Generator.Element {
precondition((startIndex ..< endIndex).contains(position), "out of bounds")
let dictionaryElement = contents[position]
return (element: dictionaryElement.0, count: dictionaryElement.1)
}
}
struct Structs<Element: Hashable> {
private var contents = [Element: Int]()
var uniqueCount: Int {
return contents.count
}
var totalCount: Int {
return contents.values.reduce(0) { $0 + $1 }
}
init() {
}
init<S: SequenceType where S.Generator.Element == Element>(_ sequence: S) {
sequence.forEach {
add($0)
}
}
init<S: SequenceType where S.Generator.Element == (key: Element, value: Int)>(_ sequence: S) {
sequence.forEach { element, count in
add(element, occurrences: count)
}
}
mutating func add(member: Element, occurrences: Int = 1) {
precondition(occurrences > 0, "Can only add a positive number of occurences")
if let currentCount = contents[member] {
contents[member] = currentCount + occurrences
}
else {
contents[member] = occurrences
}
}
mutating func remove(member: Element, occurrences: Int = 1) {
guard let currentCount = contents[member] where currentCount >= occurrences else {
preconditionFailure("Remove non-existent elements")
}
precondition(occurrences > 0, "Can only remove a positive number of occurrences")
if currentCount > occurrences {
contents[member] = currentCount - occurrences
}
else {
contents.removeValueForKey(member)
}
}
}
// Usage
let s: Structs = ["hello": 1, "goodbye": 2]
print(s)
print(s.uniqueCount)
print(s.totalCount)
s.forEach { name, value in
print(name)
print(value)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment