From 8f3788d0b27aa8e590ea7ae0646fcb273133b66e Mon Sep 17 00:00:00 2001 From: Levi McCallum Date: Fri, 5 Feb 2016 11:15:40 -0800 Subject: [PATCH] Update LCS diffing to support insertions before deletions --- AsyncDisplayKit/Private/NSArray+Diffing.m | 40 +++++++++++++---------- AsyncDisplayKitTests/ArrayDiffingTests.m | 6 ++-- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/AsyncDisplayKit/Private/NSArray+Diffing.m b/AsyncDisplayKit/Private/NSArray+Diffing.m index 00893d14..c9fd3983 100644 --- a/AsyncDisplayKit/Private/NSArray+Diffing.m +++ b/AsyncDisplayKit/Private/NSArray+Diffing.m @@ -21,29 +21,33 @@ { NSIndexSet *commonIndexes = [self _asdk_commonIndexesWithArray:array compareBlock:comparison]; - if (insertions) { - NSArray *commonObjects = [self objectsAtIndexes:commonIndexes]; - NSMutableIndexSet *insertionIndexes = [NSMutableIndexSet indexSet]; - for (NSInteger i = 0, j = 0; i < commonObjects.count || j < array.count;) { - if (i < commonObjects.count && j < array.count && comparison(commonObjects[i], array[j])) { - i++; j++; - } else { - [insertionIndexes addIndex:j]; - j++; - } + NSArray *commonObjects = [self objectsAtIndexes:commonIndexes]; + NSMutableIndexSet *insertionIndexes = [NSMutableIndexSet indexSet]; + for (NSInteger i = 0, j = 0; i < commonObjects.count || j < array.count;) { + if (i < commonObjects.count && j < array.count && comparison(commonObjects[i], array[j])) { + i++; j++; + } else { + [insertionIndexes addIndex:j]; + j++; } - *insertions = insertionIndexes; } - - if (deletions) { - NSMutableIndexSet *deletionIndexes = [NSMutableIndexSet indexSet]; - for (NSInteger i = 0; i < self.count; i++) { - if (![commonIndexes containsIndex:i]) { - [deletionIndexes addIndex:i]; + *insertions = insertionIndexes; + + NSMutableIndexSet *deletionIndexes = [NSMutableIndexSet indexSet]; + NSInteger offset = 0; + NSInteger insertionIndex = -1; + for (NSInteger i = 0; i < self.count; i++) { + if (![commonIndexes containsIndex:i]) { + // Offset deletions such that insertions are performed first + NSInteger j = [insertionIndexes indexLessThanOrEqualToIndex:i]; + if (j != NSNotFound && insertionIndex < j) { + offset++; + insertionIndex = j; } + [deletionIndexes addIndex:i + offset]; } - *deletions = deletionIndexes; } + *deletions = deletionIndexes; } - (NSIndexSet *)_asdk_commonIndexesWithArray:(NSArray *)array compareBlock:(BOOL (^)(id lhs, id rhs))comparison diff --git a/AsyncDisplayKitTests/ArrayDiffingTests.m b/AsyncDisplayKitTests/ArrayDiffingTests.m index 636af908..a96e2b52 100644 --- a/AsyncDisplayKitTests/ArrayDiffingTests.m +++ b/AsyncDisplayKitTests/ArrayDiffingTests.m @@ -46,19 +46,19 @@ @[@"bob", @"alice", @"dave"], @[@"gary", @"alice", @"dave", @"jack"], @[@0, @3], - @[@0], + @[@1], ], @[ @[@"bob", @"alice", @"dave", @"judy", @"lynda", @"tony"], @[@"gary", @"bob", @"suzy", @"tony"], @[@0, @2], - @[@1, @2, @3, @4], + @[@2, @4, @5, @6], ], @[ @[@"bob", @"alice", @"dave", @"judy"], @[@"judy", @"dave", @"alice", @"bob"], @[@1, @2, @3], - @[@0, @1, @2], + @[@0, @2, @4], ], ];