【问题标题】:Comparing values in historic manner between 2 lists and increment the values if element is from first list or decerement if it's from second list - C#以历史方式比较两个列表之间的值,如果元素来自第一个列表,则增加值,如果元素来自第二个列表,则减少值 - C#
【发布时间】:2018-04-17 02:53:08
【问题描述】:

我需要准备一个图表,其中需要显示 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 = 1 }

根据上述数据,我得到了特定周内已关闭问题的总数。

这是这些列表的代码:

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

现在剩下的最后一部分是使用这 2 个列表中的值创建一个新列表,其中应包含一周内未解决的问题总数。

解释:

  1. 我需要以历史方式(从最旧到最新)比较上述 2 个列表中的周值。
  2. 从这两个列表中获取最早的周值。 (从上面的示例数据来看,它应该是 2015 年 6 月 14 日,它在 openIssuesList 中。)以这种方式从上述 2 个列表中继续获取周(从最旧到最新)。
  3. 如果周值来自第一个列表,即openIssuesList,则增加 Count 值,方法是添加它的 Count 值使用之前获取的元素的 Count 值(现在出现在新的第三个列表中)(如果有)。
  4. 如果周值来自第二个列表,即closedIssuesList,则减少 Count 值减去它的Count 值使用之前获取的元素的 Count 值(现在出现在新的第三个列表中)(如果有)。
  5. 如果周值相等(如示例数据中的 2017 年 7 月 9 日),则首先 添加 openIssues 列出之前获取的元素(现在出现在新的第三个列表中)(如果有),然后减去这个新计算的值 与 closedIssues 列表的 Count 值。

所以从上面提供的示例数据来看,新列表应该是这样的:

[0]: { Week = {6/14/2015 12:00:00 AM}, Count = 1 }    // 0+1 = 0 : Oldest week value of all - (fetched from openIssuesList)
[1]: { Week = {12/13/2015 12:00:00 AM}, Count = 0 }  // 1-1 = 0  (fetched from closedIssuesList)
[2]: { Week = {3/5/2017 12:00:00 AM}, Count = 1 }  // 0+1 = 1 - (fetched from openIssuesList)
[3]: { Week = {5/21/2017 12:00:00 AM}, Count = 5 }  // 1+4 = 5 - (fetched from openIssuesList)
[4]: { Week = {6/4/2017 12:00:00 AM}, Count = 12 }  // 5+7 = 12 - (fetched from openIssuesList)
[5]: { Week = {6/11/2017 12:00:00 AM}, Count = 16}  // 12+4 = 16 - (fetched from openIssuesList)
[6]: { Week = {6/18/2017 12:00:00 AM}, Count = 14 }  // 16-2 = 14  (fetched from closedIssuesList)
[7]: { Week = {6/25/2017 12:00:00 AM}, Count = 21 } //14+7 = 21  (fetched from openIssuesList)
[8]: { Week = {7/9/2017 12:00:00 AM}, Count = 21 }   // These is common week from both lists. So 20 + (openIssuesList Count value) - (closedIssuesList Count value) i.e [21 + 3 - 3 = 21].
[9]: { Week = {7/23/2017 12:00:00 AM}, Count = 13 }  // 21-8 = 13  (fetched from closedIssuesList)
[10]: { Week = {8/6/2017 12:00:00 AM}, Count = 10 }   // 13-3 = 10  (fetched from closedIssuesList)
[11]: { Week = {9/17/2017 12:00:00 AM}, Count = 9 }    // 10-1 = 9  (fetched from closedIssuesList)
[12]: { Week = {10/1/2017 12:00:00 AM}, Count = 3 }    // 9-6 = 3  (fetched from closedIssuesList)

请从以上数据中查看此列表的第 8 个元素。 此列表中 2017 年 7 月 9 日的一周在 openIssuesList(第 6 个元素)和 closedIssuesList(第 2 个元素)中都很常见

实现这个列表的代码是什么?

注意:我必须从这些列表中的所有 DateTime 值中删除代码中的 Time 元素值。因此,这些列表中的所有日期值都以 12:00:00 AM 出现。

【问题讨论】:

  • 你已经修正了你的计算,除了最后两行之外它们现在是正确的:计数应该是 9 (10 - 1) 和 3 (9 - 6)。
  • 修正了我的计算。

标签: c# asp.net entity-framework list linq


【解决方案1】:

按周对所有问题进行分组,然后根据当前总计数以及给定周打开和关闭问题的总和计算计数:

int totalCount = 0;
var issuesByWeek = from issue in getDetails
                   where issue.ChangedTo == "Open" || issue.ChangedTo == "Closed"
                   group issue by issue.Date.EndOfWeek() into g
                   orderby g.Key
                   select new
                   {
                       Week = g.Key,
                       Count = totalCount += g.Sum(i => i.ChangedTo == "Open" ? 1 : -1)
                   };

您不需要两个列表来计算此统计信息。如果您需要这些列表用于其他目的,那么您可以简单地将它们连接起来并使用

from issue in openIssuesList.Concat(closedIssuesList)

三周的测试数据

var issues = new[]
{
    new Issue { Date = DateTime.Today.AddDays(-16), ChangedTo = "Open" },
    new Issue { Date = DateTime.Today.AddDays(-15), ChangedTo = "Unknown" },
    new Issue { Date = DateTime.Today.AddDays(-15), ChangedTo = "Open" },
    new Issue { Date = DateTime.Today.AddDays(-9), ChangedTo = "Closed" },
    new Issue { Date = DateTime.Today.AddDays(-8), ChangedTo = "Open" },
    new Issue { Date = DateTime.Today.AddDays(-6), ChangedTo = "Closed" },
    new Issue { Date = DateTime.Today.AddDays(-5), ChangedTo = "Closed" }
};

输出:

[
  { "Week": "2017-10-22T00:00:00+03:00", "Count": 2 }, // 0 + 2
  { "Week": "2017-10-29T00:00:00+03:00", "Count": 1 }, // 2 + 1 - 2
  { "Week": "2017-11-05T00:00:00+03:00", "Count": 0 }  // 1 - 1
]

扩展方法用于提高可读性:

public static class DateTimeExtensions
{
    public static DateTime EndOfWeek(this DateTime date) => 
       date.AddDays(date.DayOfWeek == DayOfWeek.Sunday ? 0 : 7 - (int)date.DayOfWeek).Date;
}

注意:考虑使用枚举而不是字符串来表示问题状态

【讨论】:

  • 选择它作为正确答案,因为它比@Dan Dumitru 答案更有效/更快,并且不需要对我现有的代码进行任何更改。
【解决方案2】:

基于my previous answer,我扩展了辅助类

public class WeekCount
{
    public DateTime Week { get; set; }
    public int Count { get; set; }
    public bool IsOpen { get; set; }
}

,您仍然需要修改您的选择才能使用它

.Select(x => new WeekCount { Week = x.Key, Count = x.Count() })

,代码变为:

var totalIssuesList = openIssuesList.Select(o => new WeekCount { Week = o.Week, Count = o.Count, IsOpen = true }).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(new WeekCount { Week = closedWeekCount.Week, Count = closedWeekCount.Count, IsOpen = false });
    }
}

totalIssuesList = totalIssuesList.OrderBy(twc => twc.Week).ToList();

var currentCount = 0;

foreach (var totalWeekCount in totalIssuesList)
{
    if (totalWeekCount.IsOpen)
    {
        currentCount += totalWeekCount.Count;
    }
    else
    {
        currentCount -= totalWeekCount.Count;
    }

    totalWeekCount.Count = currentCount;
}

请注意,您的某些计算是错误的,应该是,例如:

[4]: { 周 = {6/4/2017 12:00:00 AM},计数 = 12 } // 5+7 = 12

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-27
    • 2020-10-23
    • 1970-01-01
    相关资源
    最近更新 更多