Skip to content

Instantly share code, notes, and snippets.

@vhart
Created June 7, 2018 18:49
Show Gist options
  • Save vhart/7ce9ac7d2ed10d8be9567614c328b7a4 to your computer and use it in GitHub Desktop.
Save vhart/7ce9ac7d2ed10d8be9567614c328b7a4 to your computer and use it in GitHub Desktop.
Writing Filters Using KeyPaths
struct Filter<Object> {
let path: PartialKeyPath<Object>
let matcher: (Any) -> Bool
init<Type>(keyPath: KeyPath<Object, Type>, matcher: @escaping (Type) -> Bool) {
self.path = keyPath
self.matcher = { value in
guard let typedValue = value as? Type else { return false }
return matcher(typedValue)
}
}
func matches(_ value: Any) -> Bool {
return matcher(value)
}
}
class MyClass {
let name: String
let number: Int
let someBool: Bool
init(name: String, number: Int, bool: Bool) {
self.name = name
self.number = number
self.someBool = bool
}
}
let filters: [Filter<MyClass>] = [
Filter(keyPath: \MyClass.name, matcher: { value in value == "hello"}),
Filter(keyPath: \MyClass.number, matcher: { value in value == 3 }),
Filter(keyPath: \MyClass.someBool, matcher: { value in value == true })
]
func object<T>(_ object: T, matches filters: [Filter<T>]) -> Bool {
for filter in filters {
guard filter.matches(object[keyPath: filter.path]) else { return false }
}
return true
}
let obj1 = MyClass(name: "yo", number: 3, bool: false)
let obj2 = MyClass(name: "hello", number: 3, bool: true)
print(object(obj1, matches: filters))
print(object(obj2, matches: filters))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment