Created
December 27, 2017 01:28
-
-
Save NachoSoto/b6b9608e400802103d38ece4a4204885 to your computer and use it in GitHub Desktop.
Example of how to extract unique elements from a sequence in Swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
extension Sequence { | |
// Extension on Sequence allows us to use this method on Arrays, Maps, Sets, etc. | |
func uniqueElements<Index: Hashable>(for indexer: (Element) -> Index) -> [Element] { | |
// Keep track of what we've already seen in a Set, | |
// which allows us to query for elements efficiently. | |
var seenElements: Set<Index> = [] | |
var result: [Element] = [] | |
// Simple implementation looping through the sequence. | |
// That means that the computational complexity of this is O(n log n). | |
// In other words, only a little bit worse than linear complexity. | |
// | |
// This could be done in other ways (using NSOrderedSet for example), | |
// but this is just for illustration purposes (see https://twitter.com/olearydan/status/945702613596721152). | |
for element in self { | |
let index = indexer(element) | |
guard !seenElements.contains(index) else { | |
continue | |
} | |
seenElements.insert(index) | |
result.append(element) | |
} | |
return result | |
} | |
} | |
// If the elements of a sequence are already Hashable, we can define a shorthand. | |
extension Sequence where Element: Hashable { | |
var uniqueElements: [Element] { | |
return self.uniqueElements { $0 } | |
} | |
} | |
/// --------------- Examples ------------ | |
struct Person { | |
let name: String | |
let id: Int | |
} | |
let numbers = [1, 2, 3, 1, 2, 3, 4, 1, 2] | |
numbers.uniqueElements | |
let people: [Person] = [ | |
Person(name: "Nacho", id: 1), | |
Person(name: "Dan", id: 2), | |
Person(name: "Nacho", id: 3), | |
Person(name: "Steve", id: 4) | |
] | |
// We can also "index" them by a different property | |
people.uniqueElements { $0.name } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment