XDocument select distinct elements using LINQ

你离开我真会死。 提交于 2021-02-19 08:15:31

问题


I am trying to get a distinct list of elements but it always returns everything.

Xml:

<root>
    <row>
        <unit>CAN</unit>
    </row>
    <row>
        <unit>KG</unit>
    </row>
    <row>
        <unit>KG</unit>
    </row>
    <row>
        <unit>PKT</unit>
    </row>
    <row>
        <unit>CAN</unit>
    </row>
    <row>
        <unit>PKT</unit>
    </row>
    <row>
        <unit>KG</unit>
    </row>
</root>

Linq:

List<XElement> elements = (from e in xdoc.Descendants("row").Elements()
     where e.Name.Equals("unit")
     select e).Distinct().ToList();

Expected output: elements list should contain 3 items

    <unit>CAN</unit>
    <unit>KG</unit>
    <unit>PKT</unit>

回答1:


Distinct() does not know what part of the XElement to compare, so it will just compare the object reference. Since all XElements are separate objects, no matter the content, it will return them all.

You either have to define an IEqualityComparer that allows it to compare them (probably the preferred way to do it) or just use GroupBy that can take a lambda that will allow it to compare the actual Value instead;

var elements = (from e in xdoc.Root.Elements("row").Elements("unit")
                select e).GroupBy(x => x.Value).Select(x => x.First());

Output:

<unit>CAN</unit>
<unit>KG</unit>
<unit>PKT</unit>



回答2:


select e.Value,

   from e in xdoc.Descendants("row").Elements()
 where e.Name.Equals("unit")
 select e.Value).Distinct().ToList();



回答3:


I would group and take the first item in each group:

    XDocument doc = XDocument.Load("../../XMLFile1.xml");

    List<XElement> distinctUnits =
        (from unit in doc.Root.Elements("row").Elements("unit")
         group unit by (string)unit into g
         select g.First()).ToList();

    foreach (XElement unit in distinctUnits)
    {
        Console.WriteLine(unit);
    }



回答4:


this will get the result

      List<XElement> elements = new List<XElement>();

     foreach (var item in xdoc.Descendants().Where(c => c.Name == "unit").Select(c=>c))
        {
            if (elements.Where(c => c.Value == item.Value).FirstOrDefault() == null)
            {
                elements.Add(item);
            }
        }


  <unit>CAN</unit>
  <unit>KG</unit>
   <unit>PKT</unit>



回答5:


This works for me:

var query = (from e in xml.Root.Elements("row").Elements("unit")
         select e).GroupBy(e => e.Value).Select(x => x.First());

EDIT: Whoops-- I overlooked the 'distinct' requirement. Amending the above answer using Joachim Isaksson's lambda expression. Here's the new output:

<unit>CAN</unit> 
<unit>KG</unit> 
<unit>PKT</unit> 


来源:https://stackoverflow.com/questions/12097185/xdocument-select-distinct-elements-using-linq

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!