LINQ считать XML-элементы с кратными - PullRequest
0 голосов
/ 16 октября 2018

У меня есть небольшая проблема здесь, и, возможно, из-за того, что я устала, у меня возникают проблемы с объяснением моей проблемы словами, но я хочу в основном группировать, за исключением того, что элементы XML могут иметь несколько одинаковыхвид элемента.Я пытаюсь сделать это в C #, используя LINQ Пример: у меня есть этот 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

но я не могупохоже, программа заботится об элементах test2 после первого в данном элементе test1.Кроме того, первый пост здесь, так что, если я что-то напортачу, давай по мне

Ответы [ 3 ]

0 голосов
/ 16 октября 2018

Я бы сделал это в два шага:

Во-первых, извлеките уникальные 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;
    }
}
0 голосов
/ 16 октября 2018

Спасибо за помощь, но утром у меня возникла искра вдохновения, и я понял это самостоятельно:

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()}");

Или, по крайней мере, это дает правильный ответ, и этокажется, что он делает то, что я хочу

0 голосов
/ 16 октября 2018
Console.WriteLine(string.Join("\n", test.XPathSelectElements("//test2")
    .GroupBy(x => x.Value, (k, g) => $"{k}: {g.Count()}")
));
...