使用 LINQ 的不同字典

lok*_*wal 4 c# xml linq linq-to-xml

我正在尝试使用 LINQ 获取不同值的字典。我试过用这个:

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);
Run Code Online (Sandbox Code Playgroud)

这里的问题是,当有重复的条目时,roleUri就会发生错误。我正在解析 XML 文档并制作 xElement 属性的字典,roleUri以及roleref它们是否存在于 xElement 中。

另一种解决方法是使用 for 循环:

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);
                }
            }
Run Code Online (Sandbox Code Playgroud)

但我想使用 LINQ 来实现这一点。

Mar*_*zek 7

您可以编写自己的Distinct方法Func<T,TKey>作为参数。您可以在此处找到示例:基于 LINQ 中任意键的不同对象列表

使用该方法,您应该能够编写:

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);
Run Code Online (Sandbox Code Playgroud)

更新

或者您可以使用分组:

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());
Run Code Online (Sandbox Code Playgroud)