Solved

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

Posted on 2013-06-03
8
940 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 62

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
 
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
DevOps Toolchain Recommendations

Read this Gartner Research Note and discover how your IT organization can automate and optimize DevOps processes using a toolchain architecture.

 

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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Loop not working 29 47
vb.net - How to check if current user is an administrator? 6 34
SSL https .net web site force redirect 3 36
C# Single Form 8 27
Many of us here at EE write code. Many of us write exceptional code; just as many of us write exception-prone code. As we all should know, exceptions are a mechanism for handling errors which are typically out of our control. From database errors, t…
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
Windows 10 is mostly good. However the one thing that annoys me is how many clicks you have to do to dial a VPN connection. You have to go to settings from the start menu, (2 clicks), Network and Internet (1 click), Click VPN (another click) then fi…
Learn how to create flexible layouts using relative units in CSS.  New relative units added in CSS3 include vw(viewports width), vh(viewports height), vmin(minimum of viewports height and width), and vmax (maximum of viewports height and width).

910 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

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now