Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Distinct Dictionary Using LINQ

I am trying to get the dictionary of distinct values using LINQ. I have tried using this:

var roleRefList = 
    xDocument.Root.Descendants()
             .Where(x => x.Name.LocalName.Equals("roleRef") && 
                         !string.IsNullOrEmpty(Convert.ToString(x.Attributes().FirstOrDefault(a => a.Name.LocalName.Equals("roleURI")))) && 
                         !string.IsNullOrEmpty(Convert.ToString(x.Attributes().FirstOrDefault(a => a.Name.LocalName.Equals("href")))))
             .Select(l => new {
                  roleUri = l.Attributes().FirstOrDefault(a => a.Name.LocalName.Equals("roleURI")).Value,
                  href = l.Attributes().FirstOrDefault(a => a.Name.LocalName.Equals("href")).Value
              })
             .Distinct()
             .ToDictionary(a => a.roleUri);

The problem here is that when there are duplicate entries in the roleUri then an error occurs. I am parsing the XML document and making a dictionary of xElement attributes roleUri and roleref if they are present in the xElement.

The other workaround is using a for loop:

Dictionary<string, string> roleRefList = new Dictionary<string, string>();
            foreach (XElement element in xDocument.Root.Descendants().Where(x => x.Name.LocalName.Equals("roleRef")))
            {
                string roelUri = Convert.ToString(element.Attributes().FirstOrDefault(a => a.Name.LocalName.Equals("roleURI")));
                string href = Convert.ToString(element.Attributes().FirstOrDefault(a => a.Name.LocalName.Equals("href")));
                if (!string.IsNullOrEmpty(roelUri) && !string.IsNullOrEmpty(href) && !roleRefList.ContainsKey(roelUri))
                {
                    roleRefList.Add(roelUri, href);
                }
            }

but I want to implement this using LINQ.

like image 615
lokendra jayaswal Avatar asked Jan 13 '23 23:01

lokendra jayaswal


1 Answers

You could write your own Distinct method that would take Func<T,TKey> as an argument. You can find example of that here: Distinct list of objects based on an arbitrary key in LINQ

With that method you should be able to write:

var roleRefList = xDocument.Root.Descendants().Where(x => x.Name.LocalName.Equals("roleRef") && !string.IsNullOrEmpty(Convert.ToString(x.Attributes().FirstOrDefault(a => a.Name.LocalName.Equals("roleURI")))) && !string.IsNullOrEmpty(Convert.ToString(x.Attributes().FirstOrDefault(a => a.Name.LocalName.Equals("href")))))
                           .Select(l => new
                           {
                               roleUri = l.Attributes().FirstOrDefault(a => a.Name.LocalName.Equals("roleURI")).Value,
                               href = l.Attributes().FirstOrDefault(a => a.Name.LocalName.Equals("href")).Value
                           }).Distinct(l => l.roleUri).ToDictionary(a => a.roleUri);

Update

Or you can use grouping:

var roleRefList = xDocument.Root.Descendants().Where(x => x.Name.LocalName.Equals("roleRef") && !string.IsNullOrEmpty(Convert.ToString(x.Attributes().FirstOrDefault(a => a.Name.LocalName.Equals("roleURI")))) && !string.IsNullOrEmpty(Convert.ToString(x.Attributes().FirstOrDefault(a => a.Name.LocalName.Equals("href")))))
                           .Select(l => new
                           {
                               roleUri = l.Attributes().FirstOrDefault(a => a.Name.LocalName.Equals("roleURI")).Value,
                               href = l.Attributes().FirstOrDefault(a => a.Name.LocalName.Equals("href")).Value
                           })
                           .GroupBy(l => l.roleUri)
                           .ToDictionary(g => g.Key, g => g.FirstOrDefault());
like image 197
MarcinJuraszek Avatar answered Jan 30 '23 16:01

MarcinJuraszek