Skip to content

Instantly share code, notes, and snippets.

@RedRoserade
Created March 24, 2015 21:44
Show Gist options
  • Save RedRoserade/f34256ab0b362367bc82 to your computer and use it in GitHub Desktop.
Save RedRoserade/f34256ab0b362367bc82 to your computer and use it in GitHub Desktop.
IEnumerable<T> Differ
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace SoftInsa.Link.Web.Extensions
{
public static class IEnumerableExtensions
{
/// <summary>
/// Diffs this IEnumerable with another one.
/// </summary>
/// <typeparam name="K">The type of the key that will be used to identify items.</typeparam>
/// <typeparam name="T">The type of the value.</typeparam>
/// <param name="other">The enumerable which will be diffed.</param>
/// <param name="keySelector">A function which extracts the key for identification.</param>
/// <param name="valueComparer">A function which is used to compare values.</param>
/// <returns></returns>
public static EnumerableDifference<K, T> DiffBy<K, T>(this IEnumerable<T> enumerable, IEnumerable<T> other, Func<T, K> keySelector, Func<T, T, bool> valueComparer = null)
{
var existingItems = enumerable
.ToDictionary(keySelector, i => i);
var otherItems = other
.ToDictionary(keySelector, i => i);
var newItems = otherItems.Where(i => !existingItems.Keys.Contains(i.Key)).Select(i => i.Value);
var removedItems = existingItems.Where(i => !otherItems.Keys.Contains(i.Key)).Select(i => i.Value);
var changedItems = new List<Diff<K, T>>();
var unchangedItems = new List<T>();
var commonItems = existingItems
.Join(otherItems, i => i.Key, o => o.Key, (i, o) => new Tuple<T, T>(i.Value, o.Value));
foreach (var item in commonItems)
{
if (valueComparer(item.Item1, item.Item2))
{
changedItems.Add(new Diff<K, T> { Key = keySelector(item.Item1), Old = item.Item1, New = item.Item2 });
}
else
{
unchangedItems.Add(item.Item1);
}
}
return new EnumerableDifference<K, T>
{
New = newItems,
Removed = removedItems,
Changed = changedItems,
Unchanged = unchangedItems
};
}
}
public class EnumerableDifference<K, T>
{
public IEnumerable<T> New { get; set; }
public IEnumerable<Diff<K, T>> Changed { get; set; }
public IEnumerable<T> Unchanged { get; set; }
public IEnumerable<T> Removed { get; set; }
}
public class Diff<TKey, TValue>
{
public TKey Key { get; set; }
public TValue Old { get; set; }
public TValue New { get; set; }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment