diff --git a/ListDiff/Diff.cs b/ListDiff/Diff.cs
new file mode 100644
index 0000000..97fa5a8
--- /dev/null
+++ b/ListDiff/Diff.cs
@@ -0,0 +1,178 @@
+//
+// Copyright (c) Krueger Systems, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace ListDiff
+{
+ ///
+ /// TODO
+ ///
+ static partial class DiffModule
+ {
+ ///
+ /// TODO
+ ///
+ public static List<(A, T, T)> Diff (IEnumerable source, IEnumerable destination,
+ A update, A add, A remove) =>
+ Diff (source, destination, update, add, remove, out _);
+
+ ///
+ /// TODO
+ ///
+ public static List<(A, T, T)> Diff (IEnumerable source, IEnumerable destination,
+ A update, A add, A remove,
+ out bool containsOnlyUpdates) =>
+ Diff (source, destination, (s, d) => EqualityComparer.Default.Equals (s, d),
+ update, add, remove, out containsOnlyUpdates);
+
+ ///
+ /// TODO
+ ///
+ public static List<(A, S, D)> Diff (IEnumerable source, IEnumerable destination,
+ Func match,
+ A update, A add, A remove) =>
+ Diff (source, destination, match, update, add, remove, out _);
+
+ ///
+ /// TODO
+ ///
+ public static List<(A, S, D)> Diff (IEnumerable source, IEnumerable destination,
+ Func match,
+ A update, A add, A remove,
+ out bool containsOnlyUpdates) =>
+ Diff (source, destination, match, (s, d) => (update, s, d),
+ d => (add, default, d),
+ s => (remove, s, default),
+ out containsOnlyUpdates);
+
+ ///
+ /// TODO
+ ///
+ public static List Diff (IEnumerable source, IEnumerable destination,
+ Func updateResult, Func addResult, Func removeResult) =>
+ Diff (source, destination, updateResult, addResult, removeResult, out _);
+
+ ///
+ /// TODO
+ ///
+ public static List Diff (IEnumerable source, IEnumerable destination,
+ Func updateResult, Func addResult, Func removeResult,
+ out bool containsOnlyUpdates) =>
+ Diff (source, destination, (s, d) => EqualityComparer.Default.Equals (s, d),
+ updateResult, addResult, removeResult, out containsOnlyUpdates);
+
+ ///
+ /// TODO
+ ///
+ public static List Diff (IEnumerable source, IEnumerable destination,
+ Func match,
+ Func updateResult, Func addResult, Func removeResult) =>
+ Diff (source, destination, match, updateResult, addResult, removeResult, out _);
+
+ ///
+ /// TODO
+ ///
+ public static List Diff (IEnumerable source, IEnumerable destination,
+ Func match,
+ Func updateResult, Func addResult, Func removeResult,
+ out bool containsOnlyUpdates)
+ {
+ if (source == null) throw new ArgumentNullException (nameof (source));
+ if (destination == null) throw new ArgumentNullException (nameof (destination));
+ if (match == null) throw new ArgumentNullException (nameof (match));
+
+ IList x = source as IList ?? source.ToArray ();
+ IList y = destination as IList ?? destination.ToArray ();
+
+ var actions = new List ();
+
+ var m = x.Count;
+ var n = y.Count;
+
+ var start = 0;
+
+ while (start < m && start < n && match (x[start], y[start])) {
+ start++;
+ }
+
+ while (start < m && start < n && match (x[m - 1], y[n - 1])) {
+ m--;
+ n--;
+ }
+
+ //
+ // Construct the C matrix
+ //
+ var c = new int[m - start + 1, n - start + 1];
+ for (var i = 1; i <= m - start; i++) {
+ for (var j = 1; j <= n - start; j++) {
+ if (match (x[i - 1], y[j - 1])) {
+ c[i, j] = c[i - 1, j - 1] + 1;
+ }
+ else {
+ c[i, j] = Math.Max (c[i, j - 1], c[i - 1, j]);
+ }
+ }
+ }
+
+ //
+ // Generate the actions
+ //
+ for (int i = 0; i < start; i++) {
+ actions.Add (updateResult (x[i], y[i]));
+ }
+
+ var varContainsOnlyUpdates = true;
+ GenDiff (m, n);
+
+ for (int i = 0; i < x.Count - m; i++) {
+ actions.Add (updateResult (x[m + i], y[n + i]));
+ }
+
+ containsOnlyUpdates = varContainsOnlyUpdates;
+ return actions;
+
+ void GenDiff (int i, int j)
+ {
+ if (i > start && j > start && match (x[i - 1], y[j - 1])) {
+ GenDiff (i - 1, j - 1);
+ actions.Add (updateResult (x[i - 1], y[j - 1]));
+ }
+ else {
+ if (j > start && (i == start || c[i - start, j - start - 1] >= c[i - start - 1, j - start])) {
+ GenDiff (i, j - 1);
+ varContainsOnlyUpdates = false;
+ actions.Add (addResult (y[j - 1]));
+ }
+ else if (i > start && (j == start || c[i - start, j - start - 1] < c[i - start - 1, j - start])) {
+ GenDiff (i - 1, j);
+ varContainsOnlyUpdates = false;
+ actions.Add (removeResult (x[i - 1]));
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/ListDiff/ListDiff.cs b/ListDiff/ListDiff.cs
index 80aa03b..0a05a5c 100644
--- a/ListDiff/ListDiff.cs
+++ b/ListDiff/ListDiff.cs
@@ -23,7 +23,7 @@
using System;
using System.Collections.Generic;
using System.Text;
-using System.Linq;
+using static ListDiff.DiffModule;
namespace ListDiff
{
@@ -136,57 +136,12 @@ public ListDiff (IEnumerable source, IEnumerable destination)
/// Predicate used to match source and destination items
public ListDiff (IEnumerable source, IEnumerable destination, Func match)
{
- if (source == null) throw new ArgumentNullException (nameof (source));
- if (destination == null) throw new ArgumentNullException (nameof (destination));
- if (match == null) throw new ArgumentNullException (nameof (match));
-
- IList x = source as IList ?? source.ToArray ();
- IList y = destination as IList ?? destination.ToArray ();
-
- Actions = new List> ();
-
- var m = x.Count;
- var n = y.Count;
-
- var start = 0;
-
- while (start < m && start < n && match (x[start], y[start])) {
- start++;
- }
-
- while (start < m && start < n && match (x[m - 1], y[n - 1])) {
- m--;
- n--;
- }
-
- //
- // Construct the C matrix
- //
- var c = new int[m - start + 1, n - start + 1];
- for (var i = 1; i <= m - start; i++) {
- for (var j = 1; j <= n - start; j++) {
- if (match (x[i - 1], y[j - 1])) {
- c[i, j] = c[i - 1, j - 1] + 1;
- }
- else {
- c[i, j] = Math.Max (c[i, j - 1], c[i - 1, j]);
- }
- }
- }
-
- //
- // Generate the actions
- //
- for (int i = 0; i < start; i++) {
- Actions.Add (new ListDiffAction (ListDiffActionType.Update, x[i], y[i]));
- }
-
- ContainsOnlyUpdates = true;
- GenDiff (c, x, y, start, m, n, match);
-
- for (int i = 0; i < x.Count - m; i++) {
- Actions.Add (new ListDiffAction (ListDiffActionType.Update, x[m + i], y[n + i]));
- }
+ Actions = Diff (source, destination, match,
+ (s, d) => new ListDiffAction (ListDiffActionType.Update, s, d),
+ d => new ListDiffAction (ListDiffActionType.Add, default, d),
+ s => new ListDiffAction (ListDiffActionType.Remove, s, default),
+ out var containsOnlyUpdates);
+ ContainsOnlyUpdates = containsOnlyUpdates;
}
void GenDiff (int[,] c, IList x, IList y, int start, int i, int j, Func match)
@@ -341,4 +296,6 @@ public static ListDiff Diff (this
return new ListDiff (source, destination, match);
}
}
+
+ public partial class DiffModule {}
}
diff --git a/ListDiff/ListDiff.csproj b/ListDiff/ListDiff.csproj
index cc3603a..c78481c 100644
--- a/ListDiff/ListDiff.csproj
+++ b/ListDiff/ListDiff.csproj
@@ -11,4 +11,8 @@
bin\Release\netstandard1.0\ListDiff.xml
+
+
+
+
diff --git a/Tests/ListDiffTests.cs b/Tests/ListDiffTests.cs
index 50554aa..c68cafd 100644
--- a/Tests/ListDiffTests.cs
+++ b/Tests/ListDiffTests.cs
@@ -1,4 +1,5 @@
using ListDiff;
+using static ListDiff.DiffModule;
using Xunit;
namespace ListDiffTests
@@ -22,8 +23,13 @@ public class Tests
[InlineData ("abc", "", "-(a)-(b)-(c)")]
public void SimpleCases (string left, string right, string expectedDiff)
{
- var diff = left.Diff (right);
- Assert.Equal (expectedDiff, diff.ToString ());
+ var diff1 = left.Diff (right);
+
+ Assert.Equal (expectedDiff, diff1.ToString ());
+
+ var diff2 = Diff (left, right, (s, _) => s.ToString (), d => $"+({d})", s => $"-({s})");
+
+ Assert.Equal (expectedDiff, string.Join (string.Empty, diff2));
}
[Theory]
@@ -43,9 +49,13 @@ public void DiffMiddleModificationOfLongList (int listSize)
var modified = sb.ToString ().Remove (middleIndex, 1);
var expectedDiff = modified.Insert (middleIndex, string.Format("-({0})", middleItem));
- var diff = original.Diff (modified);
+ var diff1 = original.Diff (modified);
+
+ Assert.Equal (expectedDiff, diff1.ToString ());
+
+ var diff2 = Diff (original, modified, (s, _) => s.ToString (), d => $"+({d})", s => $"-({s})");
- Assert.Equal (expectedDiff, diff.ToString ());
+ Assert.Equal (expectedDiff, string.Join (string.Empty, diff2));
}
[Fact]