Skip to content

Instantly share code, notes, and snippets.

@natecook1000
Last active January 15, 2019 16:03
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 natecook1000/2665e7b845eef9fd3951a0b559069ee3 to your computer and use it in GitHub Desktop.
Save natecook1000/2665e7b845eef9fd3951a0b559069ee3 to your computer and use it in GitHub Desktop.
extension OrderedCollectionDifference {
public func inferringMoves<T: Hashable>(by f: (ChangeElement) -> T) -> OrderedCollectionDifference<ChangeElement> {
let removeDict: [T: Int?] = {
var res = [T: Int?](minimumCapacity: Swift.min(removals.count, insertions.count))
for r in removals {
let key = f(r.element)
if res[key] != .none {
res[key] = .some(.none)
} else {
res[key] = .some(r.offset)
}
}
return res.filter { (_, v) -> Bool in v != .none }
}()
let insertDict: [T :Int?] = {
var res = [T :Int?](minimumCapacity: Swift.min(removals.count, insertions.count))
for i in insertions {
let key = f(i.element)
if res[key] != .none {
res[key] = .some(.none)
} else {
res[key] = .some(i.offset)
}
}
return res.filter { (_, v) -> Bool in v != .none }
}()
return OrderedCollectionDifference.init(validatedChanges: map({ (c: OrderedCollectionDifference<ChangeElement>.Change) -> OrderedCollectionDifference<ChangeElement>.Change in
switch c {
case .remove(offset: let o, element: let e, associatedWith: _):
let key = f(e)
if removeDict[key] == nil {
return c
}
if let assoc = insertDict[key] {
return .remove(offset: o, element: e, associatedWith: assoc)
}
case .insert(offset: let o, element: let e, associatedWith: _):
let key = f(e)
if insertDict[key] == nil {
return c
}
if let assoc = removeDict[key] {
return .insert(offset: o, element: e, associatedWith: assoc)
}
}
return c
}))
}
}
struct Person: Equatable {
var uuid: String
var name: String
var employer: String
}
let before = [
Person(uuid: "4628c50f-4516-4d52-ad30-28ed81b3c1b3",
name: "Chris Lattner",
employer: "Apple"),
Person(uuid: "6a5ff808-91e0-4b1a-a4dc-37b30704c8a1",
name: "Mark Zuckerberg",
employer: "Facebook")
]
let after = [
Person(uuid: "4628c50f-4516-4d52-ad30-28ed81b3c1b3",
name: "Chris Lattner",
employer: "Google"),
Person(uuid: "2e683426-801c-4754-924c-95920fc760a5",
name: "Bill Gates",
employer: "Microsoft")
]
let diff = before
.difference(from: after)
.inferringMoves(by: { $0.uuid })
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment