Skip to content

Instantly share code, notes, and snippets.

@pwelter34
Created May 10, 2019 18:10
Show Gist options
  • Save pwelter34/6f6754c5758df87fe47c261ecbb02051 to your computer and use it in GitHub Desktop.
Save pwelter34/6f6754c5758df87fe47c261ecbb02051 to your computer and use it in GitHub Desktop.
Compare two lists giving edits, creates and deletes
using System;
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using Xunit;
namespace DeltaCompare.Tests
{
public class DeltaCompareTests
{
[Fact]
public void CompareInt()
{
var existing = new List<int> {1, 2, 3, 4, 5};
var current = new List<int> {1, 3, 5, 7};
var delta = DeltaCompare.Compare(existing, current);
delta.Should().NotBeNull();
delta.Created.Should().NotBeNullOrEmpty();
delta.Created.Should().HaveCount(1);
delta.Created.Should().IntersectWith(new[] {7});
delta.Deleted.Should().NotBeNullOrEmpty();
delta.Deleted.Should().HaveCount(2);
delta.Deleted.Should().IntersectWith(new[] {2, 4});
delta.Matched.Should().NotBeNullOrEmpty();
delta.Matched.Should().HaveCount(3);
delta.Matched.Should().IntersectWith(new[] {1, 3, 5});
}
[Fact]
public void CompareUser()
{
var existing = new List<User>
{
new User {Id = new Guid("a956a1f2-f544-4c59-8c9d-8d1ce506d404"), Name = "Name 1"},
new User {Id = new Guid("efd95a4f-0f66-4f34-99b4-94e32adfc1d2"), Name = "Name 2"},
new User {Id = new Guid("b3fa9a1e-19bc-437d-9bbb-2a03d3f0156c"), Name = "Name 3"},
};
var current = new List<User>
{
new User {Id = new Guid("efd95a4f-0f66-4f34-99b4-94e32adfc1d2"), Name = "Name 2"},
new User {Id = new Guid("b3fa9a1e-19bc-437d-9bbb-2a03d3f0156c"), Name = "Name 3"},
new User {Id = new Guid("de7693fa-b090-41aa-bbeb-f68b9aed13c5"), Name = "Name 4"},
};
var comparer = Equality<User>.CreateComparer(p => p.Id);
var delta = DeltaCompare.Compare(existing, current, comparer);
delta.Should().NotBeNull();
delta.Created.Should().NotBeNullOrEmpty();
delta.Created.Should().HaveCount(1);
delta.Deleted.Should().NotBeNullOrEmpty();
delta.Deleted.Should().HaveCount(1);
delta.Matched.Should().NotBeNullOrEmpty();
delta.Matched.Should().HaveCount(2);
}
}
public class User
{
public Guid Id { get; set; }
public string Name { get; set; }
}
public static class DeltaCompare
{
public static Delta<T> Compare<T>(IEnumerable<T> existing, IEnumerable<T> current, IEqualityComparer<T> comparer = null)
{
if (comparer == null)
comparer = EqualityComparer<T>.Default;
var existingList = existing.ToList();
var currentList = current.ToList();
var matched = existingList.Intersect(currentList, comparer);
var created = currentList.Except(existingList, comparer);
var deleted = existingList.Except(currentList, comparer);
return new Delta<T>
{
Created = created,
Deleted = deleted,
Matched = matched
};
}
}
public class Delta<T>
{
public IEnumerable<T> Matched { get; set; }
public IEnumerable<T> Created { get; set; }
public IEnumerable<T> Deleted { get; set; }
}
public static class Equality<TComparer>
{
public static IEqualityComparer<TComparer> CreateComparer<TKey>(Func<TComparer, TKey> keySelector)
{
return CreateComparer(keySelector, null);
}
public static IEqualityComparer<TComparer> CreateComparer<TKey>(Func<TComparer, TKey> keySelector, IEqualityComparer<TKey> comparer)
{
return new KeyEqualityComparer<TComparer, TKey>(keySelector, comparer);
}
}
public class KeyEqualityComparer<TComparer, TKey> : IEqualityComparer<TComparer>
{
private readonly Func<TComparer, TKey> _keySelector;
private readonly IEqualityComparer<TKey> _comparer;
public KeyEqualityComparer(Func<TComparer, TKey> keySelector, IEqualityComparer<TKey> comparer)
{
_keySelector = keySelector ?? throw new ArgumentNullException(nameof(keySelector));
_comparer = comparer ?? EqualityComparer<TKey>.Default;
}
public bool Equals(TComparer x, TComparer y)
{
return _comparer.Equals(_keySelector(x), _keySelector(y));
}
public int GetHashCode(TComparer obj)
{
return _comparer.GetHashCode(_keySelector(obj));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment