【问题标题】:Summing and grouping values求和和分组值
【发布时间】:2017-04-03 22:51:29
【问题描述】:

从我的 xml 测试报告中,我需要对缺陷进行加权求和,对每个项目和所有日期的总和进行分组。最后,我需要一些可以在网站上以图表形式显示的列表。我坚持最后一点来提取列表。

我已经附上了我到目前为止的 xml 和代码片段。

namespace LinqTest
{
    class Program
    {
        static void Main(string[] args)
        {
            int WDCFact_1 = 5;
            int WDCFact_2 = 10;
            int WDCFact_3 = 20;

            XDocument test = XDocument.Load(@"..\..\Helpers\XMLFile1.xml");
            var selected = from p in test.Descendants("Sample")
                           group p by p.Element("Date").Value into gDate
                           from projects in
                               (from proj in gDate
                                group proj by proj.Element("Project").Value)
                           select new
                           {
                               Date = DateTime.Parse(gDate.Key),
                               proj = projects.Key,
                               WDC = projects.Sum(t => (t.Element("Severity3") == null || t.Element("Severity3").Value == "") ? 0 : (int)t.Element("Severity3") * WDCFact_3) +
                                     projects.Sum(t => (t.Element("Severity1") == null || t.Element("Severity1").Value == "") ? 0 : (int)t.Element("Severity1") * WDCFact_1) +
                                     projects.Sum(t => (t.Element("Severity2") == null || t.Element("Severity2").Value == "") ? 0 : (int)t.Element("Severity2") * WDCFact_2)
                           };

            var allprj = (from p in selected
                         select p.proj).Distinct().ToList();

            var prj = from p in selected.GroupBy(d => d.Date)
                      select new
                      {
                          _d = p.LastOrDefault()
                      };

            string mybreakpoint = "";
        }
    }
}

预期结果:

List<DateTime> Dates = {12-02-2014, 13-02-2014, 14-02-2014, 15-02-2014}
List<int> WDC_prj1 = {45, 150, 65, 85}
List<int> WDC_prj2 = {110, 110, 115, 260}
List<int> WDC_prj3 = {250, 0, 235, 245}
List<int> WDC_prj4 = {170, 60, 250, 240}
List<int> WDC_prj5 = {0, 205, 0, 15}

XML 输入:

<HistoricalData xmlns:xsi="http:www.w3.org/2001/XMLSchema-instance">
    <Sample>
       <Date>12-02-2013 00:00</Date>    
       <Project>Prj1</Project>
       <Business_Line>BL1</Business_Line>    
       <Severity1>9</Severity1>
    </Sample>
    <Sample>
       <Date>12-02-2013 00:00</Date>    
       <Project>Prj2</Project>   
       <Business_Line>BL1</Business_Line>    
       <Severity1>8</Severity1>    
       <Severity2>1</Severity2>    
       <Severity3>3</Severity3>
    </Sample>
    <Sample>
       <Date>12-02-2013 00:00</Date>    
       <Project>Prj3</Project>    
       <Business_Line>BL1</Business_Line>    
       <Severity1>8</Severity1>    
       <Severity2>3</Severity2>    
       <Severity3>9</Severity3>
    </Sample>
    <Sample>
       <Date>12-02-2013 00:00</Date>    
       <Project>Prj4</Project>    
       <Business_Line>BL2</Business_Line>    
       <Severity1>2</Severity1>    
       <Severity2>0</Severity2>    
       <Severity3>8</Severity3>
    </Sample>
    <Sample>
       <Date>13-02-2013 00:00</Date>    
       <Project>Prj1</Project>    
       <Business_Line>BL1</Business_Line>    
       <Severity1>6</Severity1>    
       <Severity2>8</Severity2>    
       <Severity3>2</Severity3>
    </Sample>
    <Sample>
       <Date>13-02-2013 00:00</Date>    
       <Project>Prj2</Project>    
       <Business_Line>BL1</Business_Line>    
       <Severity1>8</Severity1>    
       <Severity2>3</Severity2>    
       <Severity3>2</Severity3>
    </Sample>
    <Sample>
      <Date>13-02-2013 00:00</Date>    
      <Project>Prj3</Project>    
      <Business_Line>BL1</Business_Line>
    </Sample>
    <Sample>
      <Date>13-02-2013 00:00</Date>    
      <Project>Prj4</Project>    
      <Business_Line>BL2</Business_Line>    
      <Severity1>0</Severity1>    
      <Severity2>6</Severity2>    
      <Severity3>0</Severity3>
    </Sample>
    <Sample>
      <Date>13-02-2013 00:00</Date>    
      <Project>Prj5</Project>    
      <Business_Line>BL1</Business_Line>    
      <Severity1>1</Severity1>    
      <Severity2>6</Severity2>    
      <Severity3>7</Severity3>
    </Sample>
    <Sample>
      <Date>14-02-2013 00:00</Date>    
      <Project>Prj1</Project>    
      <Business_Line>BL1</Business_Line>    
      <Severity1>3</Severity1>    
      <Severity2>1</Severity2>    
      <Severity3>2</Severity3>
    </Sample>
    <Sample>
      <Date>14-02-2013 00:00</Date>    
      <Project>Prj2</Project>    
      <Business_Line>BL1</Business_Line>    
      <Severity1>7</Severity1>    
      <Severity2>0</Severity2>    
      <Severity3>4</Severity3>
    </Sample>
    <Sample>
      <Date>14-02-2013 00:00</Date>    
      <Project>Prj3</Project>    
      <Business_Line>BL1</Business_Line>    
      <Severity1>7</Severity1>    
      <Severity2>4</Severity2>    
      <Severity3>8</Severity3>
    </Sample>
    <Sample>
      <Date>14-02-2013 00:00</Date>    
      <Project>Prj4</Project>    
      <Business_Line>BL2</Business_Line>    
      <Severity1>8</Severity1>    
      <Severity2>5</Severity2>    
      <Severity3>8</Severity3>
    </Sample>
    <Sample>
      <Date>15-02-2013 00:00</Date>    
      <Project>Prj1</Project>    
      <Business_Line>BL1</Business_Line>    
      <Severity1>1</Severity1>    
      <Severity2>4</Severity2>    
      <Severity3>2</Severity3>
    </Sample>
    <Sample>
      <Date>15-02-2013 00:00</Date>    
      <Project>Prj2</Project>    
      <Business_Line>BL1</Business_Line>    
      <Severity1>8</Severity1>    
      <Severity2>6</Severity2>    
      <Severity3>8</Severity3>
    </Sample>
    <Sample>
      <Date>15-02-2013 00:00</Date>    
      <Project>Prj3</Project>    
      <Business_Line>BL1</Business_Line>    
      <Severity1>1</Severity1>    
      <Severity2>8</Severity2>    
      <Severity3>8</Severity3>
    </Sample>
    <Sample>
      <Date>15-02-2013 00:00</Date>    
      <Project>Prj4</Project>    
      <Business_Line>BL2</Business_Line>    
      <Severity1>8</Severity1>    
      <Severity2>8</Severity2>    
      <Severity3>6</Severity3>
    </Sample>
    <Sample>
      <Date>15-02-2013 00:00</Date>    
      <Project>Prj5</Project>    
      <Business_Line>BL1</Business_Line>    
      <Severity1>3</Severity1>    
      <Severity2>0</Severity2>    
      <Severity3>0</Severity3>
    </Sample>
</HistoricalData>

【问题讨论】:

    标签: c# xml linq grouping


    【解决方案1】:

    这样就可以了:

    List<DateTime> Dates = selected.Select(each => each.Date).Distinct().ToList();
    List<int> WDC_prj1 = selected
        .Where(sample => sample.proj == "Prj1")
        .Select(sample => sample.WDC).ToList();
    List<int> WDC_prj2 = selected
        .Where(sample => sample.proj == "Prj2")
        .Select(sample => sample.WDC).ToList();
    // etc.
    

    请注意,您的样本中实际上并不存在 2014 年日期(您给出的结果是您的预期结果)(那里全是 2013 年),但我认为这是一个错字,您想要的只是一个不同日期的列表。

    编辑:

    好的,我刚刚注意到如果 PrjX 的值被跳过,您需要一个 0 来代替。

    我的代码会给你WDC_prj5 = {205, 15},而你实际上想要{0, 205, 0, 15}(因为在前四个样本之后没有Prj5)。

    我们可以通过在循环中迭代样本并跟踪丢失的Prjs 来满足这一要求。然后 - 每次我们再次遇到Prj1 - 我们用零替换它们。

    例如:

    var values = Enumerable.Range(1, 5).ToDictionary(n => n, n => new List<int>());
    bool firstIteration = true;
    var visited = new BitArray(5, false);
    foreach(var sample in selected)
    {
        int number = Int32.Parse(sample.proj.Last().ToString());
        visited[number - 1] = true;
        if (number == 1 && !firstIteration)
        {
            for (int i = 0; i < 5; i++)
            {
                if (!visited[i])
                    values[i + 1].Add(0);
            }
            visited.SetAll(false);
        }
        values[number].Add(sample.WDC);
        firstIteration = false;
    }
    

    现在只是:

    List<int> WDC_prj1 = values[1];
    List<int> WDC_prj2 = values[2];
    

    等等

    或者,如果您认为 LINQ 很酷且性能方面的考虑不会吓到您,您可以将 BitArray 扔掉:

    foreach(var sample in selected)
    {
        int number = Int32.Parse(sample.proj.Last().ToString());
        if (number == 1)
        {
            // we just started a new cycle...
            int expectedNumberOfValues = values.Values.Max(list => list.Count);
            values = values.ToDictionary(
                kvp => kvp.Key,
                kvp => kvp.Value.Concat(Enumerable.Repeat(0, expectedNumberOfValues - kvp.Value.Count)).ToList());
        }
        values[number].Add(sample.WDC);
    }
    

    收集结果保持不变:

    List<int> WDC_prj1 = values[1];
    List<int> WDC_prj2 = values[2];
    

    PS。

    另外,请注意DateTime.Parse

    它是文化敏感的,它可能会在另一个版本的 Windows 上崩溃。

    例如,在我的计算机上,它在尝试解析 13-02-2013 00:00 时崩溃(并且它错误地将 12-02-2013 解析为 12 月 2 日)。

    在这种情况下,您最好改用DateTime.ParseExact(d, "dd-MM-yyyy HH:mm", CultureInfo.InvariantCulture)。即使它只应该在您的 PC 上运行——我无法知道——它仍然是一个好习惯。

    【讨论】:

    • 这很神奇 :-) 对 DateTime.Parse 的评论。只是想知道如何将日期提取到类似的列表中。
    • @ThomasB 我的代码为您提供了与所需输出相同的确切日期列表(除了 2013/2014 混淆)。所以如果结果不符合你的期望,我需要知道是什么方式
    猜你喜欢
    • 2021-03-27
    • 1970-01-01
    • 2020-10-07
    • 2021-11-22
    • 1970-01-01
    • 2013-02-13
    • 2015-05-22
    • 2020-09-16
    • 1970-01-01
    相关资源
    最近更新 更多