我需要准备一张图表,其中我需要显示3行。一个用于显示一周的新问题,一个用于一周的已结束问题,第三个用于一周的总公开问题。出于这个原因,我准备了一个查询,并且能够成功创建2个单独的列表 - 一个列表维护每周新发布的计数,第二个列表维护每周的已结算问题计数。
以下是第一个列表的示例数据(维护新问题的列表):
[0]: { Week = {6/14/2015 12:00:00 AM}, Count = 1 }
[1]: { Week = {3/5/2017 12:00:00 AM}, Count = 1 }
[2]: { Week = {5/21/2017 12:00:00 AM}, Count = 4 }
[3]: { Week = {6/4/2017 12:00:00 AM}, Count = 7 }
[4]: { Week = {6/11/2017 12:00:00 AM}, Count = 4 }
[5]: { Week = {6/25/2017 12:00:00 AM}, Count = 7 }
[6]: { Week = {7/9/2017 12:00:00 AM}, Count = 3 }
根据以上数据,我得到了特定周的未决问题总数。
注意:对于这两个列表,周值包含星期日的日期。因为我需要从星期一开始的一周,同时在图表中显示数据。
类似地,对于第二个列表的样本数据(一个维持已关闭的问题):
[0]: { Week = {12/13/2015 12:00:00 AM}, Count = 1 }
[1]: { Week = {7/9/2017 12:00:00 AM}, Count = 3 }
[2]: { Week = {6/18/2017 12:00:00 AM}, Count = 2 }
[3]: { Week = {7/23/2017 12:00:00 AM}, Count = 8 }
[4]: { Week = {10/1/2017 12:00:00 AM}, Count = 6 }
[5]: { Week = {8/6/2017 12:00:00 AM}, Count = 3 }
[6]: { Week = {9/17/2017 12:00:00 AM}, Count = 5 }
根据以上数据,我得到了特定周的已结算问题的总数。
以下是这些列表的代码:
var openIssuesList = getDetails.Where(x => x.ChangedTo == "Open").Select(x => new { Week = x.Date.AddDays(x.Date.DayOfWeek == DayOfWeek.Sunday ? 0 : 7 - (int)x.Date.DayOfWeek).Date, Detail = x }).GroupBy(x => x.Week).Select(x => new { Week = x.Key, Count = x.Count() }).ToList();
var closedIssuesList = getDetails.Where(x => x.ChangedTo == "Closed").Select(x => new { Week = x.Date.AddDays(x.Date.DayOfWeek == DayOfWeek.Sunday ? 0 : 7 - (int)x.Date.DayOfWeek).Date, Detail = x }).GroupBy(x => x.Week).Select(x => new { Week = x.Key, Count = x.Count() }).ToList();
现在剩下的最后一块是使用这两个列表中的值来创建一个新列表,这两个列表应包含一周内总开放问题的数据。
说明:
所以从上面提供的示例数据中可以看出新列表应该如何:
[0]: { Week = {6/14/2015 12:00:00 AM}, Count = 1 } // As is value from first list - openIssuesList
[1]: { Week = {12/13/2015 12:00:00 AM}, Count = 1 } // As is value from second list - closedIssuesList
[2]: { Week = {3/5/2017 12:00:00 AM}, Count = 1 } // As is value from first list - openIssuesList
[3]: { Week = {5/21/2017 12:00:00 AM}, Count = 4 } // As is value from first list - openIssuesList
[4]: { Week = {6/4/2017 12:00:00 AM}, Count = 7 } // As is value from first list - openIssuesList
[5]: { Week = {6/11/2017 12:00:00 AM}, Count = 4 } // As is value from first list - openIssuesList
[6]: { Week = {6/18/2017 12:00:00 AM}, Count = 2 } // As is value from second list - closedIssuesList
[7]: { Week = {6/25/2017 12:00:00 AM}, Count = 7 } // As is value from first list - openIssuesList
[8]: { Week = {7/9/2017 12:00:00 AM}, Count = 0 } // These is common week from both lists. Hence we calculate the difference between count values. So 3-3 = 0.
[9]: { Week = {7/23/2017 12:00:00 AM}, Count = 8 } // As is value from second list - closedIssuesList
[10]: { Week = {8/6/2017 12:00:00 AM}, Count = 3 } // As is value from second list - closedIssuesList
[11]: { Week = {9/17/2017 12:00:00 AM}, Count = 5 } // As is value from second list - closedIssuesList
[12]: { Week = {10/1/2017 12:00:00 AM}, Count = 6 } // As is value from second list - closedIssuesList
从上面的数据中可以看到此列表的第8个元素。这个列表中的一周7/9/2017在openIssuesList(第6个元素)和closedIssuesList(第2个元素)中很常见
实现此列表的代码是什么?
注意:我已从这些列表中的所有DateTime值中删除代码中的Time元素值。因此,所有日期值都显示在这些列表中的12:00:00 AM。
答案 0 :(得分:1)
如果您不需要LINQ解决方案,则可以创建帮助程序类
public class WeekCount
{
public DateTime Week { get; set; }
public int Count { get; set; }
}
,使用此类修改您的选择
.Select(x => new WeekCount { Week = x.Key, Count = x.Count() })
,然后简单地做:
var totalIssuesList = openIssuesList.ToList();
foreach (var closedWeekCount in closedIssuesList)
{
var totalWeekCount = totalIssuesList.FirstOrDefault(owc => owc.Week == closedWeekCount.Week);
if (totalWeekCount != null)
{
totalWeekCount.Count = totalWeekCount.Count - closedWeekCount.Count;
}
else
{
totalIssuesList.Add(closedWeekCount);
}
}
totalIssuesList = totalIssuesList.OrderBy(twc => twc.Week).ToList();
答案 1 :(得分:1)
要使用LINQ执行此操作,您可以考虑这两个列表的完全外连接。
助手类:
public class IssueCount
{
public DateTime Week { get; set; }
public int Count { get; set; }
}
然后
// Union left outer join and right outer join to perform full outer join
// https://stackoverflow.com/a/5491381/5682608
var leftOuterJoin = from newIssue in newIssues
join closedIssue in closedIssues
on newIssue.Week equals closedIssue.Week
into temp
from closedIssue in temp.DefaultIfEmpty(new IssueCount { Week = newIssue.Week, Count = 0 })
select new IssueCount
{
Week = newIssue.Week,
Count = newIssue.Count - closedIssue.Count
};
var rightOuterJoin = closedIssues.Where(issue => !newIssues.Select(newIssue => newIssue.Week).Contains(issue.Week));
// Modified: Following code can generate duplicated entries when
// 2 IssueCounts of the same Week have different values in Count property
//
//var rightOuterJoin = from closedIssue in closedIssues
// join newIssue in newIssues
// on closedIssue.Week equals newIssue.Week
// into temp
// from newIssue in temp.DefaultIfEmpty(new IssueCount { Week = closedIssue.Week, Count = 0 })
// select new IssueCount
// {
// Week = closedIssue.Week,
// Count = closedIssue.Count - newIssue.Count
// };
var fullOuterJoin = leftOuterJoin.Union(rightOuterJoin);
foreach (var issue in fullOuterJoin.OrderBy(i => i.Week))
{
Console.WriteLine($"{issue.Week.ToString("MM/dd/yyyy")} : {issue.Count}");
}
这应输出
06/14/2015 : 1
12/13/2015 : 1
03/05/2017 : 1
05/21/2017 : 4
06/04/2017 : 7
06/11/2017 : 4
06/18/2017 : 2
06/25/2017 : 7
07/09/2017 : 0
07/23/2017 : 8
08/06/2017 : 3
09/17/2017 : 5
10/01/2017 : 6