如何区分价值观?

时间:2012-09-24 10:27:49

标签: c# xml linq linq-to-xml distinct

我正在尝试构建一个选择唯一值组的查询。我知道如何对值进行分组并选择不同的值,但我不知道如何选择不同的值组,而不考虑所考虑的元素的顺序。更确切地说:

我的XML是这样的:

<A>
    <B type="1">value1</prop>
    <B type="2">value2</prop>
    <B type="3">value3</prop>
    <B type="4">value4</prop>
<C>
    <D>XXX</D>
</C>
<C>
    <D>YYY</D>
</C>
</A>

<A>
    <B type="3">value3</prop>
    <B type="4">value4</prop>
    <B type="2">value2</prop>
<C>
    <D>XXX</D>
</C>
<C>
    <D>YYY</D>
</C>
</A>

在这里,我想从所有<B>节点中创建<A>个值组,并仅选择唯一的值集。例如,这里:

value1 + value2 + value3 + value4

值2 +值3 + VALUE4 + VALUE1

如果某些或所有值不同,这两组值应该是唯一的。

非常感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

以下作品:

var doc = XDocument.Parse(xml);

var comparer = new ElementsComparer();

var result = doc.Descendants("B")
                .GroupBy(x => x.Parent)
                .Distinct(comparer);

class ElementsComparer : IEqualityComparer<IGrouping<XElement, XElement>>,
                         IEqualityComparer<XElement>
{
    public bool Equals(XElement lhs, XElement rhs)
    {
        return lhs.Value.Equals(rhs.Value);
    }

    public bool Equals(IGrouping<XElement, XElement> lhs,
                       IGrouping<XElement, XElement> rhs)
    {
        var x = lhs.OrderBy(a => a.Value);
        var y = rhs.OrderBy(a => a.Value);
        return x.SequenceEqual(y, this);
    }

    public int GetHashCode(XElement obj)
    {
        return obj.Value.GetHashCode();
    }

    public int GetHashCode(IGrouping<XElement, XElement> obj)
    {
        return 0;
    }
}

这将返回不同的组。如果组中的元素与另一组中的元素具有相同的值,则组被视为与另一组相同 不幸的是,我们需要一个完整的IEqualityComparer实现来实现这一目标。

答案 1 :(得分:0)

尝试

var xDocument = XDocument.Parse(/*Your XML here*/);
var vals =
    //Find all A-Elements
    xDocument.Root.Elements("A")
        //Select all their B-Elements to one collection
        .SelectMany(a => a.Elements("B"))
        //Group the B-Items by their value
        .GroupBy(element => element.Value)
        //Select the keys of the IGrouping<TValue, XElement>
        .Select(element => element.Key)
        //Distinct them
        .Distinct();