Solved

List<Dictionary<string, string>> how do I get a set of distinct columns?

Posted on 2013-06-03
8
1,023 Views
Last Modified: 2013-06-05
I currently have a List<Dictionary<string, string>>, and I need distinct columns.

This collection has many values about a user: firstname, lastname, email, etc.  Not all values are distinct in the entire dictionary, but I need the distinct values for certain columns, like mentioned above.

so:
bob, smith, bob@gmail.com, 5
bob, smith, bob@gmail.com, 6
karen, smith, karen@gmail.com, 7
karen, smith, karen@gmail.com, 8

I want
bob, smith, bob@gmail.com
karen, smith, karen@gmail.com

so basically a distinct, but only for certain columns, but I want the results to also be a List<Dictionary<string, string>>.
0
Comment
Question by:jackjohnson44
8 Comments
 
LVL 63

Expert Comment

by:Fernando Soto
ID: 39217387
Hi jackjohnson44;

The List<Dictionary<string, string>> can have many dictionaries in the list, you want to have each dictionary  in itself to have Distinct column values?

In the Dictionary you have the Key and Value as you defined it to both be of type string. Is the Key to column and the value the column value which you want to be Distinct?

Can you also show what values will be in a typical key and what value is in the Value of that dictionary entry.
0
 
LVL 42

Expert Comment

by:sedgwick
ID: 39218292
i assume that each dictionary in the list is user's properties (key -> property name, value -> property value).
if u want to distincy by columns, u need to specify the columns which u want to distinct, then using linq u can group the dictionary by the property values.
0
 

Author Comment

by:jackjohnson44
ID: 39220037
Hi guys,
Sorry, I am not following your questions.

I have a list of dictionaries which are all the same.  In this instance, I only need some of the columns.

MyDictList[0]["FirstName"] = "bob"
MyDictList[0]["LastName"] = "smith"
MyDictList[0]["OtherColumn"] = "1"

MyDictList[1]["FirstName"] = "bob"
MyDictList[1]["LastName"] = "smith"
MyDictList[1]["OtherColumn"] = "2"

MyDictList[2]["FirstName"] = "Karen"
MyDictList[2]["LastName"] = "smith"
MyDictList[2]["OtherColumn"] = "1"

MyDictList[3]["FirstName"] = "Karen"
MyDictList[3]["LastName"] = "smith"
MyDictList[3]["OtherColumn"] = "2"

I want
newDict[0]["FirstName"] = "bob"
newDict[0]["LastName"] = "smith"
newDict[1]["FirstName"] = "Karen"
newDict[1]["LastName"] = "smith"

To state it another way.  Start with my List<Dictionary<string, string>>.  Remove all columns that I am not using.  After that, do a distinct.

If this were sql
select distinct firstname, lastname from x


I can do this with linq, but it changes my output object.
0
Salesforce Made Easy to Use

On-screen guidance at the moment of need enables you & your employees to focus on the core, you can now boost your adoption rates swiftly and simply with one easy tool.

 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 39220075
I can do this with linq, but it changes my output object.
So you want the existing list of dictionaries to reflect the change? You don't want to create a new object as a result of LINQ, correct?
0
 

Author Comment

by:jackjohnson44
ID: 39220091
I want the output to be List<Dictionary<string, string>>.  It will have less dictionary items.  I don't want to create a "new object" meaning a new anonymous type.  I have a ton of functions that take in List<Dictionary<string, string>>.

to make this extremely simple:
MyDictList[0]["FirstName"] = "bob"
MyDictList[0]["LastName"] = "smith"
MyDictList[0]["OtherColumn"] = "1"

MyDictList[1]["FirstName"] = "bob"
MyDictList[1]["LastName"] = "smith"
MyDictList[1]["OtherColumn"] = "2"

I want the result to be
x[0]["FirstName"] = "bob"
x[0]["LastName"] = "smith"

List<Dictionary<string, string>> x = getDistinctFirstLastName(mydictlist);
0
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 39220200
I want the output to be List<Dictionary<string, string>>.  It will have less dictionary items.
We get that. Do you want the output to be the original List<Dictionary<string, string>>, or should it be a new, separate instance of a List<Dictionary<string, string>>?
0
 

Author Comment

by:jackjohnson44
ID: 39220273
A new one.  It will have less columns, so it would have to be different.

If I wanted to go from a list<dict<string,string>> to an anon object, I would use the code below.  I need the output to be list<dict<string,string>>.


            var dataRowsSelectedAccess = (from dr in dataRows
                                          select new
                                                     {
                                                         LastName = dr["LastName"].ToSafeString(),
                                                         FirstName = dr["FirstName"].ToSafeString(),
                                                         EmailAddress = dr["EmailAddress"].ToSafeString(),
                                                         LocationAccess = dr["LocationAccess"].ToSafeString(),
                                                         UserType = dr["UserType"].ToSafeString(),
                                                         ManagingUser = dr["ManagingUser"].ToSafeString(),
                                                         AdminApprover = dr["AdminApprover"].ToSafeString(),
                                                         Title = dr["Title"].ToSafeString(),
                                                         Profile = dr["Profile"].ToSafeString(),
                                                         LastLogin = dr["LastLogin"].ToSafeString()
                                                     }).Distinct().ToList();
0
 
LVL 75

Accepted Solution

by:
käµfm³d   👽 earned 500 total points
ID: 39220454
Try the following:

string[] relevantKeys = { "FirstName", "LastName" };

var dictsWithBothKeys = MyDictList.Where(dict => relevantKeys.All(key => dict.ContainsKey(key)));
var dictsWithJustBothKeys = dictsWithBothKeys.Select(dict => dict.Keys.Where(key => relevantKeys.Contains(key))
                                                                      .ToDictionary(key => key, key => dict[key]));
var distinctDicts = dictsWithJustBothKeys.Distinct(new DictComparer(relevantKeys));

Open in new window


class DictComparer : IEqualityComparer<Dictionary<string, string>>
{
    private IEnumerable<string> _keys;

    public DictComparer(IEnumerable<string> keys)
    {
        this._keys = keys;
    }

    public bool Equals(Dictionary<string, string> x, Dictionary<string, string> y)
    {
        foreach (string key in this._keys)
        {
            if (!x.ContainsKey(key) ||
                !y.ContainsKey(key) ||
                 x[key] != y[key])
            {
                return false;
            }
        }

        return true;
    }

    public int GetHashCode(Dictionary<string, string> obj)
    {
        return 0;
    }
}

Open in new window


You might need to adjust the implementation of GetHashCode above. It seemed to work with the data you provided, but that was a small sampling.
0

Featured Post

How Do You Stack Up Against Your Peers?

With today’s modern enterprise so dependent on digital infrastructures, the impact of major incidents has increased dramatically. Grab the report now to gain insight into how your organization ranks against your peers and learn best-in-class strategies to resolve incidents.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Today I had a very interesting conundrum that had to get solved quickly. Needless to say, it wasn't resolved quickly because when we needed it we were very rushed, but as soon as the conference call was over and I took a step back I saw the correct …
It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
Finding and deleting duplicate (picture) files can be a time consuming task. My wife and I, our three kids and their families all share one dilemma: Managing our pictures. Between desktops, laptops, phones, tablets, and cameras; over the last decade…

730 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question