Okay, so you want to go for each list and determine the items that it has that aren't in at least one other list, and all of the items in at least one other list that it doesn't have.
To do that start out by finding all of the items in all lists; that is the "intersection" of each list.
Once you have that Except
does all of the work for you. All items except
a given list gives you the items that are in the intersection but not in that particular list, the items in the intersection Except
the list is all of the items missing from the intersection.
public static IEnumerable<SetDifference<T>> ComputeDifferences<T>(IList<List<T>> lists)
{
if (lists.Count == 0)
yield break;
var intersection = new HashSet<T>(lists.First());
foreach (var list in lists.Skip(1))
{
intersection.IntersectWith(list);
}
var output = new List<SetDifference<T>>();
foreach (var list in lists)
{
yield return new SetDifference<T>(
list: list,
additionalObjects: list.Except(intersection),
missingObjects: intersection.Except(list));
}
}
Here is the simple data holder used to provide the output.
public class SetDifference<T>
{
public SetDifference(List<T> list, IEnumerable<T> additionalObjects,
IEnumerable<T> missingObjects)
{
List = list;
AdditionalObjects = additionalObjects;
MissingObjects = missingObjects;
}
public List<T> List { get; private set; }
public IEnumerable<T> AdditionalObjects { get; private set; }
public IEnumerable<T> MissingObjects { get; private set; }
}
Note that because I'm using HashSet
, as well as other set operations from LINQ, it will rely on the GetHashCode
method of each of the items, so it must have an appropriate implementation given the Equals
method for that object.