LINQ用倍数计数XML元素

时间:2018-10-15 21:05:00

标签: c# xml linq group-by count

这里有点问题,可能是因为我很累,我很难用词来解释我的问题,但是我想要的基本上是一个分组依据,除了XML元素可以有多个相同的元素一种元素。我正在尝试使用LINQ示例在C#中执行此操作: 我有这个XML

<?xml version="1.0" encoding="utf-8"?>
<test>
    <test1>
        <test2>1</test2>
    </test1>
    <test1>
        <test2>2</test2>
    </test1>
    <test1>
        <test2>1</test2>
        <test2>3</test2>
        <test2>4</test2>
    </test1>
    <test1>
        <test2>1</test2>
        <test2>2</test2>
    </test1>
    <test1>
        <test2>5</test2>
    </test1>
</test>

我想计算有多少test1元素的test2元素的值为1、2等,因此输出应为:

1:3
2:2
3:1
4:1
5:1

但是我似乎无法让程序关心给定test1元素中第一个之后的test2元素。另外,在这里先发帖,所以如果我搞砸了,请放轻松

3 个答案:

答案 0 :(得分:1)

Console.WriteLine(string.Join("\n", test.XPathSelectElements("//test2")
    .GroupBy(x => x.Value, (k, g) => $"{k}: {g.Count()}")
));

答案 1 :(得分:0)

我将分两个步骤进行操作:

首先,提取要对每个test2进行计数的唯一test1值:

var test2Values = xd.Descendants("test2").Select(d => d.Value).Distinct();

第二,对于test2的每个值,计算有多少test1包含特定的test2值:

var countOfT1WithT2Values = test2Values.Select(t2v => new { t2v, t1Count = xd.Descendants("test1").Where(t1 => t1.Descendants("test2").Any(t2 => t2.Value == t2v)).Count() });

注意:这并不是特别有效,因为它在XML上进行了多次传递。如果需要效率,则应在test1后代上使用循环:

var countOfT1WithT2Values = new Dictionary<string, int>();

foreach (var t1 in xd.Descendants("test1")) {
    foreach (var t2 in t1.Descendants("test2").Select(dt2 => dt2.Value)) {
        if (countOfT1WithT2Values.TryGetValue(t2, out var countForT2))
            countOfT1WithT2Values[t2] = countForT2 + 1;
        else
            countOfT1WithT2Values[t2] = 1;
    }
}

答案 2 :(得分:0)

感谢您的帮助,但今天早晨我终于有了灵感,我自己想出了办法:

XDocument xd = XDocument.Load("test.xml");
var test = xd.Root.Descendants("test2").GroupBy(x => x.Value);
foreach (var e in test)
    Console.WriteLine($"{e.Key}: {e.Count()}");

或者至少它给出了正确的答案,并且看起来像我想要的