Created
August 8, 2015 01:23
-
-
Save blixt/e461c0296e2b9162e2fd to your computer and use it in GitHub Desktop.
This file contains 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
class ListDiff<T : Hashable> { | |
typealias IndexList = [Int] | |
typealias FromIndexToIndexList = [(from: Int, to: Int)] | |
// A list of indexes of where items were added. | |
let added: IndexList | |
// A list of indexes where items that have disappeared used to be. | |
let deleted: IndexList | |
// A list of tuples of indexes representing the old and new indexes of items that moved. | |
let moved: FromIndexToIndexList | |
init(before: [T], after: [T]) { | |
// Create a map with all the items in the smaller list mapped to indexes. | |
let beforeIsSmaller = before.count < after.count | |
var map = [T: Int]() | |
for (index, item) in enumerate(beforeIsSmaller ? before : after) { | |
map[item] = index | |
} | |
var added = IndexList() | |
var deleted = IndexList() | |
var moved = FromIndexToIndexList() | |
// Loop through the longer list to calculate all changed indexes. | |
for (index1, item) in enumerate(beforeIsSmaller ? after : before) { | |
if let index2 = map[item] { | |
if (index1 != index2) { | |
let (from, to) = beforeIsSmaller ? (index2, index1) : (index1, index2) | |
moved.append((from: from, to: to)) | |
map.removeValueForKey(item) | |
} | |
} else { | |
if (beforeIsSmaller) { | |
added.append(index1) | |
} else { | |
deleted.append(index1) | |
} | |
} | |
} | |
// Handle any indexes still in the map. | |
for (_, index) in map { | |
if (beforeIsSmaller) { | |
deleted.append(index) | |
} else { | |
added.append(index) | |
} | |
} | |
self.added = added | |
self.deleted = deleted | |
self.moved = moved | |
} | |
} | |
let a = ["Anna", "Bob", "Cecilia", "Dennis", "Ellinor", "Frank"] | |
let b = ["Cecilia", "Bob", "Dennis", "Ellinor", "Gabriella", "Hubert"] | |
let myDiff = ListDiff<String>(before: a, after: b) | |
myDiff.added // [1, 5, 4] | |
myDiff.deleted // [0, 5] | |
myDiff.moved // [(from: 2, to: 0), (from: 3, to: 2), (from: 4, to: 3)] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
line 30 must be out the condition.
For testing, use: