[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1555
  • Last Modified:

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>>.
0
jackjohnson44
Asked:
jackjohnson44
1 Solution
 
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
 
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
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
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
 
käµfm³d 👽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

Featured Post

Receive 1:1 tech help

Solve your biggest tech problems alongside global tech experts with 1:1 help.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now