How to get unique values from two list of dictionaries using Linq?

This is my code

public class Model
{
    public Model();

    public Dictionary<string, string> Data { get; set; }

}

list<dictionary<string,string>>  data1;
list<dictionary<string,string>>  data2;

data1=await get<model>();
data2=await get<model>();

data1[0]=[0][{id,101}]
         [1][{name,one}]
         [2][{marks,56}]
         [3][{state,ap}]     

data1[1]=[0][{id,102}]
         [1][{name,two}]
         [2][{marks,65}]
         [3][{state,up}]     

data1[2]=[0][{id,103}]
         [1][{name,three}]
         [2][{marks,89}]
         [3][{state,usa}]     



data2[0]=[0][{roleid,101}]
         [1][{stdname,one}]
data2[1]=[0][{roleid,102}]
         [1][{stdname,two}]

Finally i want Output Like

data3[0]=[0][{id,103}]
         [1][{name,three}]
         [2][{marks,89}]
         [3][{state,usa}]     

in the above code i have two list of dictionaries, i want to get unqiue id values compare two lists.the above two lists key names are different get except values from two lists based on first list id and second list roleid.

Upvotes: 4

Views: 1546

Answers (2)

deramko
deramko

Reputation: 2835

If you want to compare the dictionaries using their Id you must implement a custom comparer

public class DictComparerById : IEqualityComparer<Dictionary<string, string>>
{
    public bool Equals(Dictionary<string, string> x, Dictionary<string, string> y)
    {
        // Two dictionary are equal if the have the same "id"
        string idX;
        if(!x.TryGetValue("id", out idX))
            x.TryGetValue("roleid", out idX);

        string idY;
        if(!y.TryGetValue("id", out idY))
            y.TryGetValue("roleid", out idY);

        return (idX == idY);
    }

    public int GetHashCode(Dictionary<string, string> x)
    {
        string id;
        if(!x.TryGetValue("id", out id))
            x.TryGetValue("roleid", out id);
        return id.GetHashCode();
    }
}

Then you can use

var dictCmp = new DictComparerById();
var data3 = data1
    .Union(data2, dictCmp)
    .Except(data1.Intersect(data2, dictCmp), dictCmp);

Upvotes: 2

Maor Veitsman
Maor Veitsman

Reputation: 1564

Assuming you would like to intersect to lists:

Use the intersect method. First implement a comparer between two dictionaries:

public class DictComparer : IEqualityComparer<Dictionary<string, string>>
{
    public bool Equals(Dictionary<string, string> x, Dictionary<string, string> y)
    {
        return (x == y) || (x.Count == y.Count && !x.Except(y).Any());
    }

    public int GetHashCode(Dictionary<string, string> x)
    {
        var ret = 123;
        foreach (var keyValue in x)
        {
            ret = ret + (keyValue.GetHashCode() * 31);
        }
        return ret;
    }
}

Then use it like this:

var result = data1.Union(data2).Except(data1.Intersect(data2, new DictComparer()), new DictComparer());

Edit: noticed he wanted the exact opposite. Changed the function accordingly. Edit2: I was missing a proper implementation of GetHashCode for dictionaries. This implementation seems to work: link

Upvotes: 2

Related Questions