Skip to content

Instantly share code, notes, and snippets.

@loromits
Created April 25, 2019 08:26
Show Gist options
  • Save loromits/6800402bc8b2ff1aa139dae1a7b892d6 to your computer and use it in GitHub Desktop.
Save loromits/6800402bc8b2ff1aa139dae1a7b892d6 to your computer and use it in GitHub Desktop.
extension Array {
/// Union with newElements, comparing by keyPath value and replacing old elements with new
/// Expected complexity ~ 3*n
func union<T: Hashable>(newElements: Array, byKeyPath keyPath: KeyPath<Element, T>) -> Array {
var copy = self
// Hash indices for faster replacement
let sample = copy.enumerated().reduce(into: [T: Index]()) { result, entry in
result[entry.element[keyPath: keyPath]] = entry.offset
}
copy.reserveCapacity(copy.count + newElements.count)
// Either replace element if it is `equal` or append to the end
for element in newElements {
if let index = sample[element[keyPath: keyPath]] {
copy[index] = element
} else {
copy.append(element)
}
}
return copy
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment