Skip to content

Instantly share code, notes, and snippets.

@natecook1000
Last active November 12, 2018 12:28
Show Gist options
  • Select an option

  • Save natecook1000/3cbe7710ec0002588feed8512468dfc6 to your computer and use it in GitHub Desktop.

Select an option

Save natecook1000/3cbe7710ec0002588feed8512468dfc6 to your computer and use it in GitHub Desktop.
ContainmentSet & PredicateSet
protocol ContainmentSet {
associatedtype SetElement
func contains(_ element: SetElement) -> Bool
func intersection(_: Self) -> Self
func union(_: Self) -> Self
func subtracting(_: Self) -> Self
func symmetricDifference(_: Self) -> Self
}
extension Set : ContainmentSet {
typealias SetElement = Element
}
struct PredicateSet<T> : ContainmentSet {
func contains(_ element: T) -> Bool {
return predicate(element)
}
func symmetricDifference<U: ContainmentSet>(_ other: U) -> PredicateSet<T>
where U.SetElement == T {
return PredicateSet { e in self.contains(e) != other.contains(e) }
}
func subtracting<U: ContainmentSet>(_ other: U) -> PredicateSet<T>
where U.SetElement == T {
return PredicateSet { e in self.contains(e) && !other.contains(e) }
}
func union<U: ContainmentSet>(_ other: U) -> PredicateSet<T>
where U.SetElement == T {
return PredicateSet { e in self.contains(e) || other.contains(e) }
}
func intersection<U: ContainmentSet>(_ other: U) -> PredicateSet<T>
where U.SetElement == T {
return PredicateSet { e in self.contains(e) && other.contains(e) }
}
func invert() -> PredicateSet {
return PredicateSet { e in !self.contains(e) }
}
let predicate: (T) -> Bool
}
// ---------------------------------------------
// Basic usage
let evens = PredicateSet { $0 % 2 == 0 }
evens.contains(3) // f
evens.contains(4) // t
let positives = PredicateSet { $0 > 0 }
let evenPositives = evens.intersection(positives)
evenPositives.contains(4) // t
evenPositives.contains(-4) // f
let s: Set = [1, 2, 3]
let evensPlus123 = evens.union(s)
evensPlus123.contains(3) // t
evensPlus123.contains(4) // t
// ---------------------------------------------
// Semi-replacement for (NS)CharacterSet
typealias CharSet = PredicateSet<Character>
extension PredicateSet where T == Character {
static var whitespace: PredicateSet {
// This is almost certainly wrong
return PredicateSet { e in [" ", "\r", "\n", "\t"].contains(e) }
}
}
extension String {
func trimming(charactersIn set: CharSet) -> Substring {
guard let i = index(where: set.invert().contains)
else { return self.prefix(0) }
let j = indices.reversed().index(where: { !set.contains(self[$0]) })!.base
return self[i..<j]
}
}
" Hello! \n".trimming(charactersIn: .whitespace)
// "Hello!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment