簡體   English   中英

通過C#中的DateTime值合並對象

[英]Consolidating objects by DateTime values in C#

我在C#中具有“ BeginDate”和“ EndDate” DateTime屬性的對象列表。 當一個對象的BeginDate與24小時內的上一個EndDate匹配時,我需要創建一個包含所有對象的所有對象的新列表,直到間隔超過24小時為止。

例如。 我有一個像這樣的清單

            BeginDate    EndDate
Object 1    12/21/2017   01/20/2018
Object 2    12/01/2017   12/21/2017
Object 3    10/25/2017   12/01/2017
Object 4    09/17/2017   10/25/2017
Object 5    08/01/2017   09/02/2017
Object 6    06/25/2017   07/26/2017
Object 7    04/20/2017   06/25/2017

需要變成這樣的列表

            BeginDate    EndDate
Object 1    09/17/2017   01/20/2018
Object 2    08/01/2017   09/02/2017
Object 3    4/20/2017    07/26/2017

如果對象表示正在進行的項目,那么EndDate可能為空值,這進一步加劇了我的問題。 因此,原始開發人員選擇使用DateTime嗎? 類型,而不是該字段的常規DateTime值。 所以你可能會遇到這樣的情況

            BeginDate    EndDate
Object 1    12/21/2017   null
Object 2    12/01/2017   12/21/2017

必須將其轉換為

            BeginDate    EndDate
Object 1    12/01/2017   null

要么

            BeginDate    EndDate
Object 1    12/01/2017   (DateTime.Now)

現在,我正在嘗試這樣做,但是它並沒有完全合並所有對象:

for (var index = 0; index < ProjectList.Count; index++)
{
  Project_BL ThisProject = ProjectList[index];
  Project_BL nextProject = ProjectList[index + 1];
  if (index + 1 < ProjectList.Count && ProjectList[index+1] != null)
  {
    DateTime TempEndDate = nextProject.EndDate ?? DateTime.Now;
    TimeSpan DifferenceBetweenProjectsTimespan =
      ThisProject.BeginDate.Subtract(TempEndDate);
    int DifferenceBetweenProjects = (int)DifferenceBetweenProjectsTimespan.TotalHours;
    if (DifferenceBetweenProjects <= 24)
    {                             
      if (IsLongProject == true)
      {
        nextProject.ProjectNature = "Long-term";
      }
      nextProject.EndDate = ThisProject.EndDate;
      ProjectList.RemoveAt(index);                            
      continue;
    }
    else
    {
      ProjectList.Add(ThisProject);
      index++;
      continue;
    }
  }
  else
  {
    ProjectList.Add(ThisProject);
  }
}

return ProjectList;

有人有想法么? 我現在把頭撞在牆上。 因此,任何幫助將不勝感激。

這是我的解決方案(DotNetFiddle示例)

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main()
    {
        var projectList = new List<Project>
        {
            new Project{Name = "Object 1", BeginDate = new DateTime(2017,12,21), EndDate = new DateTime(2018,01,20)},
            new Project{Name = "Object 2", BeginDate = new DateTime(2017,12,01), EndDate = new DateTime(2017,12,21)},
            new Project{Name = "Object 3", BeginDate = new DateTime(2017,10,25), EndDate = new DateTime(2017,12,01)},
            new Project{Name = "Object 4", BeginDate = new DateTime(2017,09,17), EndDate = new DateTime(2017,10,25)},
            new Project{Name = "Object 5", BeginDate = new DateTime(2017,08,01), EndDate = new DateTime(2017,09,02)},
            new Project{Name = "Object 6", BeginDate = new DateTime(2017,06,25), EndDate = new DateTime(2017,07,26)},
            new Project{Name = "Object 7", BeginDate = new DateTime(2017,04,20), EndDate = new DateTime(2017,06,25)},
        };

        var newList = new List<Project>();

        while(projectList.Count > 0)
        {
            var item = projectList.ElementAt(0);
            projectList.Remove(item);
            newList.Add(item);

            //Console.WriteLine(item);

            var match = Match(item, projectList);

            while (match != null)
            {
                //Console.WriteLine("match: " + match.ToString());
                projectList.Remove(match);
                item.BeginDate = item.BeginDate < match.BeginDate ? item.BeginDate : match.BeginDate;
                item.EndDate = item.EndDate > match.EndDate ? item.EndDate : match.EndDate;
                item.IsLongTerm = true;
                //Console.WriteLine("adjusted: " + item.ToString());

                match = Match(item, projectList);
            }
        }

        foreach(var project in newList)
        {
            Console.WriteLine(project.ToString());
        }
    }

    private static Project Match(Project project, IEnumerable<Project> projects)
    {
        var result = projects.FirstOrDefault(p => 
            (project.BeginDate.AddDays(-1) < p.BeginDate && p.BeginDate < project.EndDate.AddDays(1) )
            || (project.BeginDate.AddDays(-1) < p.EndDate && p.EndDate < project.EndDate.AddDays(1)) );

        return result;
    }
}

public class Project
{
    public string Name { get; set; }
    public DateTime BeginDate { get; set; }
    public DateTime EndDate { get; set; }
    public bool IsLongTerm { get; set; }
    public override string ToString()
    {
        return Name + " " + BeginDate.ToString("yyyy-MM-dd") + " " + EndDate.ToString("yyyy-MM-dd");
    }
}

結果:

對象1 2017-09-17 2018-01-20

對象5 2017-08-01 2017-09-02

對象6 2017-04-20 2017-07-26

這是我嘗試使用簡化的枚舉

IEnumerable<Project> Consolidate(IEnumerable<Project> data) {
    // I need to create a new list of these objects with all the objects 
    //consolidated when the BeginDate of one object matches the EndDate 
    //of the previous one within 24 hours, going back until there is a break longer than 24 hours.
    using (var e = data.GetEnumerator()) {
        if (e.MoveNext()) {
            var previous = e.Current;
            while (e.MoveNext()) {
                var next = e.Current;
                if (previous.BeginDate.AddDays(-1) > next.EndDate) {
                    yield return previous;
                    previous = next;
                    continue;
                }
                previous = new Project {
                    BeginDate = next.BeginDate,
                    EndDate = previous.EndDate ?? DateTime.Now
                };
            }
            yield return previous;
        }
    }
}

對於上述情況(包括null結束日期),這將產生期望的結果。

如果需要,可以將其概括為擴展方法。 您只需要提供條件謂詞和構建合並對象的Func

在這里,您可以在這里找到我的示例

模型

public class Project
{
    public Project(string name, DateTime beginDate) : this(name, beginDate, null) { }
    public Project(string name, DateTime beginDate, DateTime? endDate)
    {
        Name = name;
        BeginDate = beginDate;
        EndDate = endDate;
    }

    public string Name { get; set; }
    public DateTime BeginDate { get; set; }
    public DateTime? EndDate { get; set; }

    public override string ToString()
    {
        return $"{Name}:\t{BeginDate.ToShortDateString()}\t:\t{(EndDate.HasValue ? EndDate.Value.ToShortDateString() : "Present")}";
    }
}

方法

private static List<Project> Consolidate(List<Project> projects)
{
    var result = new List<Project>();

    // if empty return
    if (!projects.Any()) return result;

    // adding first project to a new list
    // and removing it from the main list
    result.Add(projects.First());
    projects.Remove(projects.First());

    // loop over all projects in the main list
    projects.ForEach(p =>
    {
        var endDate = p.EndDate.HasValue ? p.EndDate.Value : DateTime.Today;

        // checking if any of the projects in the new list
        // starts within 24 hours of the end date of the
        // current project
        if (result.Any(r => r.BeginDate >= endDate && r.BeginDate.Subtract(endDate) <= TimeSpan.FromDays(1) && r.Name != p.Name))
        {
            // if you find any get it
            var match = result.First(r => r.BeginDate >= endDate && r.BeginDate.Subtract(endDate) <= TimeSpan.FromDays(1) && r.Name != p.Name);
            var index = result.IndexOf(match);
            // create new project that consalidate both projects
            result[index] = new Project(match.Name, p.BeginDate, match.EndDate);
        }
        else
        {
            // if didn't find any add the current 
            // project to the new list
            result.Add(p);
        }
    });

    return result;
}

樣品結果

P6: 4/20/2017   :   7/26/2017
P5: 8/1/2017    :   9/2/2017
P1: 9/17/2017   :   1/20/2018

P6: 4/20/2017   :   Present
P5: 8/1/2017    :   9/2/2017
P4: 9/17/2017   :   Present
P1: 10/25/2017  :   1/20/2018

這是我的方法...

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main()
    {
        var projectList = new List<Project>
        {
            new Project{Id = "Object 0", BeginDate = new DateTime(2018,01,20), EndDate = null},
            new Project{Id = "Object 1", BeginDate = new DateTime(2017,12,21), EndDate = new DateTime(2018,01,20)},
            new Project{Id = "Object 2", BeginDate = new DateTime(2017,12,01), EndDate = new DateTime(2017,12,21)},
            new Project{Id = "Object 3", BeginDate = new DateTime(2017,10,25), EndDate = new DateTime(2017,12,01)},
            new Project{Id = "Object 4", BeginDate = new DateTime(2017,09,17), EndDate = new DateTime(2017,10,25)},
            new Project{Id = "Object 5", BeginDate = new DateTime(2017,08,01), EndDate = new DateTime(2017,09,02)},
            new Project{Id = "Object 6", BeginDate = new DateTime(2017,06,25), EndDate = new DateTime(2017,07,26)},
            new Project{Id = "Object 7", BeginDate = new DateTime(2017,04,20), EndDate = new DateTime(2017,06,25)},
        };

        var resultsList = new List<Project>();
        var previousProject = new Project();
        var currentProject = new Project();

        foreach(var p in projectList.OrderBy(p => p.BeginDate))
        {
            if (string.IsNullOrEmpty(previousProject.Id))
            {
                previousProject = currentProject = p;
                continue;
            }

            if (p.BeginDate.AddDays(-1)<=previousProject.EndDate)
            {
                currentProject.EndDate = p.EndDate;
                previousProject = currentProject;
                continue;
            }
            else
            {
                resultsList.Add(currentProject);
                previousProject = currentProject = p;
            }
        }
        resultsList.Add(currentProject);

        foreach(var p in resultsList)
        {
            var endDate = p.EndDate?.ToString("yyyy-MM-dd");
            Console.WriteLine("{0}\t{1}\t{2}", p.Id, p.BeginDate.ToString("yyyy-MM-dd"), ((string.IsNullOrEmpty(endDate))?"Null":endDate));
        }
    }
}

public class Project
{
    public string Id { get; set; }
    public DateTime BeginDate { get; set; }
    public DateTime? EndDate { get; set; }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM