对值进行求和和分组

时间:2014-01-21 20:23:28

标签: c# xml linq grouping

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

我已经附加了xml和codesnip到目前为止我得到了多远。

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>

1 个答案:

答案 0 :(得分:2)

这样可以解决问题:

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月2日错误地解析了12-02-2013)。

在这种情况下,您最好使用DateTime.ParseExact(d, "dd-MM-yyyy HH:mm", CultureInfo.InvariantCulture)代替。即使它只能在你的电脑上工作 - 我也无从知晓 - 它仍然是一个好习惯。