7

Imagine I have a list of items:

 - A
 - B
 - C

Now from somewhere a server tells my application that element B was removed, yet it only provides the entire new list, not the exact change details. Since WinRT ListViews automatically animate addition, removal, and movement of items inside them, I would prefer not to refresh the backing list and call a Reset-INotifyCollectionChanged-event, since this animates every item looking rather blunt and rough. Instead, I want to compute the steps that are needed to transform my local list into the list that I get from the server. (Kind of like a levenshtein distance, just not with the count of steps but the with steps themselves)

e. g.:

 1. Delete element B
 2. Add new element D to position 3

How would I do that?

EDIT: Order matters in my case.

Moritz Gunz
  • 612
  • 6
  • 14

2 Answers2

3

Based on the title of the page @MihaiCaracostea suggested, I was able to find a working diff algorithm that works on any IList<T>. It even uses yield to calculate the diff lazily as you are enumerating the changes.

The article can be found here, the actual source code (if you don't want to read how it's done) is here.

Beware though, the algorithm runs in O(n²) time. There certainly is room for improvement in that area.

Moritz Gunz
  • 612
  • 6
  • 14
  • @MihaiCaracostea Yeah, it's a moment when both the question and the answer deserve upvoting :) – Eldar Dordzhiev Sep 14 '15 at 21:21
  • I'm currently putting all that code (including some additional methods for transforming one list into another) into a NuGet-library. I'll post the link here when it's done. – Moritz Gunz Sep 18 '15 at 16:58
2

Look for elements in initial list that do not exist in received list: remove them.

Look for elements in received list that do not exist in initial list: add them.

EDIT: have a look at this codeproject resource, showing a diff algorithm.

Mihai Caracostea
  • 7,896
  • 4
  • 24
  • 44
  • Order does matter in my case. – Moritz Gunz Sep 09 '15 at 21:49
  • Thanks! The sources are quite old, so I'll have to put some work into them to make them use generics and features of modern C#, but other than that, this is exactly what I was looking for. – Moritz Gunz Sep 10 '15 at 05:55
  • Okay, I checked the link and it does confuse me a bit. If I put two sets into the list: Enumerable.Range(1, 5) as source and Enumerable.Range(2, 5) as destination, I'd imagine it to tell me "delete the first element of source", then do nothing and then add the two last elements of the destination to the source. Instead it gives me [this](http://imgur.com/Ku6pXeP). Any idea what the -1 is about? – Moritz Gunz Sep 10 '15 at 16:43
  • I found another generic diff algorithm that I'll try out as well. [Link for other people having the same problem](http://devdirective.com/post/91/creating-a-reusable-though-simple-diff-implementation-in-csharp-part-1). – Moritz Gunz Sep 10 '15 at 16:51