Skip to content

Instantly share code, notes, and snippets.

@acrookston
Created October 7, 2017 02:50
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 acrookston/7a0d29c14d264919d1cd6167d570f991 to your computer and use it in GitHub Desktop.
Save acrookston/7a0d29c14d264919d1cd6167d570f991 to your computer and use it in GitHub Desktop.
// Results:
// 0.40788197517395 - IteratedEnum (it's slow due to EnumCollection)
// 0.282593011856079 - StaticIteratedEnum
// 0.152174055576324 - SwitchedEnum
// 0.159240961074829 - OtherSwitchedEnum
import Foundation
// MARK: - Benchmark - gotta know how fast it is!
func benchmark(_ operation: ()->()) -> Double {
let startTime = CFAbsoluteTimeGetCurrent()
operation()
let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime
return Double(timeElapsed)
}
// MARK: - Enum extension - lifesaver :)
protocol EnumCollection : Hashable {}
extension EnumCollection {
static func enumerated() -> AnySequence<Self> {
typealias S = Self
return AnySequence { () -> AnyIterator<S> in
var raw = 0
return AnyIterator {
let current = withUnsafePointer(to: &raw) {
$0.withMemoryRebound(to: S.self, capacity: 1) { $0.pointee }
}
guard current.hashValue == raw else { return nil }
raw += 1
return current
}
}
}
}
enum IteratedEnum: EnumCollection {
case one, two
@discardableResult init?(searching: String) {
for item in IteratedEnum.enumerated() {
if searching.contains(item.matcher) {
self = item
return
}
}
return nil
}
// If you don't want to make it a String enum `case one = "one"
private var matcher: String {
switch self {
case .one:
return "one"
case .two:
return "two"
}
}
}
enum StaticIteratedEnum: String {
case one = "one"
case two = "two"
static let all: [StaticIteratedEnum] = [.one, .two]
@discardableResult init?(searching: String) {
for item in StaticIteratedEnum.all {
if searching.contains(item.rawValue) {
self = item
return
}
}
return nil
}
}
enum SwitchedEnum: EnumCollection {
case one, two
@discardableResult init?(searching: String) {
switch true {
case searching.contains("one"):
self = .one
case searching.contains("two"):
self = .two
default:
return nil
}
}
}
enum OtherSwitchedEnum: EnumCollection {
case one, two
@discardableResult init?(searching: String) {
switch searching {
case _ where searching.contains("one"):
self = .one
case _ where searching.contains("two"):
self = .two
default:
return nil
}
}
}
assert(IteratedEnum(searching: "one") == .one)
assert(IteratedEnum(searching: "two") == .two)
assert(StaticIteratedEnum(searching: "one") == .one)
assert(StaticIteratedEnum(searching: "two") == .two)
assert(SwitchedEnum(searching: "one") == .one)
assert(SwitchedEnum(searching: "two") == .two)
assert(OtherSwitchedEnum(searching: "one") == .one)
assert(OtherSwitchedEnum(searching: "two") == .two)
let cases = ["One time", "one", "two", "four", "two times"]
let count = UInt32(cases.count)
let sample = (0...100000).map { _ in cases[Int(arc4random_uniform(count))] }
print(benchmark {
for i in sample {
IteratedEnum(searching: i)
}
})
print(benchmark {
for i in sample {
StaticIteratedEnum(searching: i)
}
})
print(benchmark {
for i in sample {
SwitchedEnum(searching: i)
}
})
print(benchmark {
for i in sample {
OtherSwitchedEnum(searching: i)
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment