Skip to content

Instantly share code, notes, and snippets.

@HakanL
Created January 12, 2016 22:11
Show Gist options
  • Save HakanL/e0c4939d0d250596cb81 to your computer and use it in GitHub Desktop.
Save HakanL/e0c4939d0d250596cb81 to your computer and use it in GitHub Desktop.
Utils to merge lists, good to use when saving stuff into a database with child objects, etc
using System;
using System.Collections.Generic;
using System.Linq;
public static class Util
{
public static void MapManyToManyAssociation<T>(
ICollection<T> currentData,
ICollection<T> newData,
Func<T, T, bool> equality,
Action<T> insert,
Action<T> delete)
{
foreach (var existing in currentData.ToList())
{
var anyMatch = newData.Any(a => equality(existing, a));
if (!anyMatch)
// Remove item
delete(existing);
}
foreach (var newItem in newData)
{
var anyMatch = currentData.Any(a => equality(newItem, a));
if (!anyMatch)
insert(newItem);
}
}
/// <summary>
/// Map the new data to the existing. Changes are handled as a delete/insert.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="currentData"></param>
/// <param name="newData"></param>
/// <param name="equality"></param>
/// <param name="insert"></param>
/// <param name="delete"></param>
/// <param name="update"></param>
public static void MapImmutableOneToMany<TCurrent, TNew>(
ICollection<TCurrent> currentData,
ICollection<TNew> newData,
Func<TCurrent, TNew, bool> equality,
Action<TNew> insert,
Action<TCurrent> delete,
Action<TCurrent, TNew> update = null)
{
var currentItemsToRemove = new List<TCurrent>();
var newDataList = newData?.ToList() ?? new List<TNew>();
foreach (var current in currentData.ToList())
{
var matchingNewEntry = newDataList.FirstOrDefault(a => equality(current, a));
if (matchingNewEntry != null)
{
newDataList.Remove(matchingNewEntry);
if (update != null)
update(current, matchingNewEntry);
}
else
delete(current);
}
// Insert new
newDataList.ForEach(a => insert(a));
}
/// <summary>
/// Map objects based on position in the lists
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="currentData"></param>
/// <param name="newData"></param>
/// <param name="assignment"></param>
/// <param name="insert"></param>
/// <param name="delete"></param>
public static void SequentialOneToManyMap<T>(
ICollection<T> currentData,
ICollection<T> newData,
Action<T, T> assignment,
Action<T> insert,
Action<T> delete)
{
var currentDataArray = currentData.ToArray();
var newDataArray = newData.ToArray();
for (int i = 0; i < currentData.Count; i++)
{
if (i < newData.Count)
// Replace
assignment(currentDataArray[i], newDataArray[i]);
}
if (currentData.Count < newData.Count)
{
// Insert new items
newDataArray.Skip(currentData.Count).ToList().ForEach(a => insert(a));
}
else if (currentData.Count > newData.Count)
{
// Delete items
currentData.Skip(newData.Count).ToList().ForEach(a => delete(a));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment