Skip to content

Instantly share code, notes, and snippets.

@numist
Last active August 29, 2015 14:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save numist/e07c49065b6e08a7ee73 to your computer and use it in GitHub Desktop.
Save numist/e07c49065b6e08a7ee73 to your computer and use it in GitHub Desktop.
A quick implementation of Sets along with some operators for performing some set arithmetic.
var thing = Set<String>()
thing.add("Hello")
thing.add(", ")
thing.add("World")
thing.add("!")
thing.remove("World")
thing.remove("!")
let bar: Set = ["Hello", "World", "!"]
println("thing: \(thing.description)") // thing: {"Hello", ", "}
println("bar: \(bar.description)") // bar: {"Hello", "World", "!"}
println("thing + bar: \((thing + bar).description)") // thing + bar: {"Hello", ", ", "World", "!"}
println("thing - bar: \((thing - bar).description)") // thing - bar: {", "}
println("thing ^ bar: \((thing ^ bar).description)") // thing ^ bar: {", ", "World", "!"}
println("thing & bar: \((thing & bar).description)") // thing & bar: {"Hello"}
import Foundation
struct SetGenerator<T:Hashable> : Generator {
var backingGenerator: DictionaryGenerator<T, Void>
init(backingGenerator: DictionaryGenerator<T, Void>) {
self.backingGenerator = backingGenerator;
}
mutating func next() -> T? {
if let (key, _) = backingGenerator.next() {
return key;
}
return nil;
}
}
struct Set<T:Hashable> : Sequence, ArrayLiteralConvertible, Printable, DebugPrintable {
static func convertFromArrayLiteral(elements: T...) -> Set<T> {
var result = Set<T>()
for i in elements {
result.add(i);
}
return result;
}
var _backingStore:Dictionary<T,Void> = [:]
var count:Int { return _backingStore.count }
var description:String {
var result = "{"
for key in _backingStore.keys {
result += "\"\(key)\", "
}
result = result.substringToIndex(countElements(result) - 2) + "}"
return result
}
var debugDescription: String { return description }
subscript (object: T) -> T? {
if _backingStore[object] != nil {
return object
}
return nil
}
func generate() -> SetGenerator<T> {
return SetGenerator(backingGenerator:_backingStore.generate())
}
mutating func add(object: T) {
_backingStore[object] = ()
}
mutating func remove(object: T) {
_backingStore[object] = nil
}
}
func +<T>(lhs: Set<T>, rhs: Set<T>) -> Set<T> {
var result = lhs
for i in rhs {
result.add(i)
}
return result
}
func -<T>(lhs: Set<T>, rhs: Set<T>) -> Set<T> {
var result = lhs
for i in rhs {
result.remove(i)
}
return result
}
func |<T>(lhs: Set<T>, rhs: Set<T>) -> Set<T> {
return lhs + rhs
}
// This could be more efficiently implemented, but this representation is simpler
func &<T>(lhs: Set<T>, rhs: Set<T>) -> Set<T> {
return (lhs + rhs) - (lhs ^ rhs)
}
// This could be more efficiently implemented, but this representation is simpler
func ^<T>(lhs: Set<T>, rhs: Set<T>) -> Set<T> {
return (lhs - rhs) + (rhs - lhs)
}
// This could be more efficiently implemented, but this representation is simpler
func ==<T>(lhs: Set<T>, rhs: Set<T>) -> Bool {
return (lhs - rhs).count == 0
}
// This could be more efficiently implemented, but this representation is simpler
func !=<T>(lhs: Set<T>, rhs: Set<T>) -> Bool {
return (lhs - rhs).count != 0
}
@assignment func +=<T>(inout lhs: Set<T>, rhs: Set<T>) {
lhs = lhs + rhs
}
@assignment func -=<T>(inout lhs: Set<T>, rhs: Set<T>) {
lhs = lhs - rhs
}
@assignment func |=<T>(inout lhs: Set<T>, rhs: Set<T>) {
lhs = lhs | rhs
}
@assignment func &=<T>(inout lhs: Set<T>, rhs: Set<T>) {
lhs = lhs & rhs
}
@assignment func ^=<T>(inout lhs: Set<T>, rhs: Set<T>) {
lhs = lhs ^ rhs
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment