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

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>>.
jackjohnson44Asked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
käµfm³d 👽Connect With a Mentor Commented:
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
 
Fernando SotoRetiredCommented:
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
 
Meir RivkinFull stack Software EngineerCommented:
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
What Kind of Coding Program is Right for You?

There are many ways to learn to code these days. From coding bootcamps like Flatiron School to online courses to totally free beginner resources. The best way to learn to code depends on many factors, but the most important one is you. See what course is best for you.

 
jackjohnson44Author Commented:
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
 
käµfm³d 👽Commented:
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
 
jackjohnson44Author Commented:
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
 
käµfm³d 👽Commented:
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
 
jackjohnson44Author Commented:
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
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.