indignatz
indignatz

Reputation: 23

LINQ - Comparing dictionaries of lists to find new and changed objects

Here is my problem:

I have two dictionaries with identical structures:

Dictionary<string, List<Object>> Existing
Dictionary<string, List<Object>> New

Basically what I need to do is to first find any List<Object> that is in New but not in Existing based on the key and then find any Object in each List<Object> contained in New that does not exist in its corresponding List<Object> in Existing or is changed based on a number of properties in Object and, of course, the dictionary key.

I'm currently doing this by looping and checking each object individually, but I thought there must be a better way to do this using LINQ.

Hopefully that is clear, but let me know if you need further info.

Thanks.

Upvotes: 2

Views: 1761

Answers (2)

AD.Net
AD.Net

Reputation: 13399

Dictionary<string, int> New = new Dictionary<string, int>();
Dictionary<string, int> Existing = new Dictionary<string, int>();

New.Add("A", 100);
New.Add("B", 200);
New.Add("Y", 300);
New.Add("X", 400);


Existing.Add("A", 1);
Existing.Add("B", 2);
Existing.Add("C", 3);
Existing.Add("D", 4);
Existing.Add("E", 5);
Existing.Add("F", 6);
Existing.Add("G", 7);
Existing.Add("H", 8);

var newStuff = New.Where(n => !Existing.ContainsKey(n.Key)).ToList();
var updatedStuff = Existing.Where(e => New.ContainsKey(e.Key) && e.Value != New.Single(n => n.Key == e.Key).Value);


newStuff.Dump();
updatedStuff.Dump();

//updated and new 
newStuff.AddRange(updatedStuff);
newStuff.Dump();

Done in Linqpad.

Upvotes: 0

Allon Guralnek
Allon Guralnek

Reputation: 16121

As for new entries in the dictionary and new objects within an entry's List<object>:

List<object>[] addedLists = New.Keys.Except(Existing.Keys)
                                    .Select(key => New[key])
                                    .ToArray();

object[] addedObjects = Existing.Keys.Intersect(New.Keys)
                                     .SelectMany(key => New[key].Except(Existing[key])
                                     .ToArray();

But the last requirement is a bit unclear. How would you define a changed object? Which objects should be compared for change? Comparing any object with any other object would potentially be defined as different, so there must be some similarities on which to base a comparison (e.g. the objects with the same value in their ID property).

EDIT: As you clarified in your comment how object identity is defined, here's how to find all changed objects (assuming the dictionary's value is a list of Foo that has a properties Name and Type that identify the object and property Value that may change:

var differences = Existing.Keys.Intersect(New.Keys).SelectMany(key =>
    from existingObj in Existing[key]
    join newObj in New[key] on new { existingObj.Name, existingObj.Type } equals
                               new { newObj.Name, newObj.Type }
    where existingObj.Value != newObj.Value
    select new { Key = key, Existing = existingObj, New = newObj });

This will produce a sequence of objects each containing the key of the dictionary the difference was found in, the existing object and the new object. Identical objects will not be included in the results.

Upvotes: 3

Related Questions