c#根据相同的开始和结束时间组合天数

本文关键字:时间 结束 组合 开始 | 更新日期: 2023-09-27 18:16:34

我想把同一家商店营业时间相似的天数合并在一起。例如,如果我们有:

Mon 9am-5pm
Tue 9am-5pm
Wed 9am-5pm
Thu 8am-6pm
Fri 8am-6pm
Sat 10am-2pm

我希望代码简化为:

Mon-Wed 9am-5pm
Thu-Fri 8am-6pm
Sat     10am-2pm
Sun     -

如果没有一长串if/else,我如何做到这一点?

c#根据相同的开始和结束时间组合天数

只是说说我的看法:

void Main()
{
    var dt = new DataTable();
    dt.Columns.Add("DayName");
    dt.Columns.Add("From");
    dt.Columns.Add("To");
    AddDay(dt, "Mon", "9am", "5pm");
    AddDay(dt, "Tue", "9am", "5pm");
    AddDay(dt, "Wed", "9am", "5pm");
    AddDay(dt, "Thu", "8am", "6pm");
    AddDay(dt, "Fri", "8am", "6pm");
    AddDay(dt, "Sat", "10am", "2pm");
    AddDay(dt, "Sun", "", "");
    var combined = GetCombinedOpeningHours(dt);
    Console.WriteLine(combined);
}
void AddDay(DataTable dt, string dayName, string fromTime, string toTime)
{
    var row = dt.NewRow();
    row["DayName"] = dayName;
    row["From"] = fromTime;
    row["To"] = toTime;
    dt.Rows.Add(row);
}
Dictionary<string,string> GetCombinedOpeningHours(DataTable dt)
{
    (dt.Columns.Add("OpeningHours")).Expression = "From+'-'+To";
    var groupedByOpeningHours = from day in dt.AsEnumerable() 
                                group day by day.Field<string>("OpeningHours") into g 
                                select g;
    var combined = new Dictionary<string,string>();
    foreach(var grp in groupedByOpeningHours)
    {
        var firstDay = grp.FirstOrDefault().Field<string>("DayName");
        var lastDay = grp.LastOrDefault().Field<string>("DayName");
        var key = (firstDay == lastDay) ? firstDay : firstDay + "-" + lastDay;
        if (!combined.ContainsKey(key))
            combined.Add(key, grp.FirstOrDefault().Field<string>("OpeningHours"));
    }
    return combined;
}

这是一种使用最小显式条件逻辑的方法。策略是:(1)将数据转换为对象;(2)基于(1)中创建的对象执行合并:

  // mimic data from databasse
  var days = new[] {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
  var openTime = new[] {"9am", "9am", "9am", "8am", "8am", "10am"};
  var closeTime = new[] {"5pm", "5pm", "5pm", "6pm", "6pm", "2pm"};
  // lookup of day code to DayOfWeek enum
  var dayOfWeekMap = Enum.GetNames(typeof(DayOfWeek))
    .ToDictionary(
      x => x.Substring(0, 3),
      x => (DayOfWeek)Enum.Parse(typeof(DayOfWeek), x));
  // convert data to objects
  var dayStoreHours =
    Enumerable.Range(0, days.Count())
      .Select(idx => new StoreHours {
        DayOfWeek = dayOfWeekMap[days[idx]],
        OpenTime = DateTime.ParseExact(
          openTime[idx],
          "htt", CultureInfo.InvariantCulture)
          .TimeOfDay,
        CloseTime = DateTime.ParseExact(
          closeTime[idx],
          "htt", CultureInfo.InvariantCulture)
          .TimeOfDay
      })
      .ToDictionary(x => x.DayOfWeek, x => x);
  // merge consecutive days if open and close time match
  var mergedStoreHours = new HashSet<MergedStoreHours>();
  var currentMergedHours = default(MergedStoreHours);
  Enum.GetNames(typeof(DayOfWeek))
    .Select(x => (DayOfWeek)Enum.Parse(typeof(DayOfWeek), x))
    .ToList()
    .ForEach(dow => {
      if (!dayStoreHours.ContainsKey(dow)) {
        // there are not hours recorded for the current day
        // create an entry for this day with identical open and close time
        mergedStoreHours.Add(
          new MergedStoreHours { 
            FirstDayOfWeek = dow, 
            LastDayOfWeek = dow
        });
        return;
      }
      var currentDayStoreHours = dayStoreHours[dow];
      if (currentMergedHours != default(MergedStoreHours) &&
          currentDayStoreHours.OpenTime == currentMergedHours.OpenTime &&
          currentDayStoreHours.CloseTime == currentMergedHours.CloseTime
        ) {
        // extend the merged hours to the current day
        currentMergedHours.LastDayOfWeek = dow;
      } else {
        currentMergedHours = new MergedStoreHours {
          FirstDayOfWeek =  dow, 
          LastDayOfWeek = dow,
          OpenTime = currentDayStoreHours.OpenTime,
          CloseTime = currentDayStoreHours.CloseTime
        };
      }
      mergedStoreHours.Add(currentMergedHours);
    });
  // order in increasing day of the week, placing sunday last
  var orderMergedHours = mergedStoreHours
    .OrderBy(x => x.FirstDayOfWeek == DayOfWeek.Sunday ? 8 : x.FirstDayOfWeek.GetHashCode())
    .ToList();

表示存储小时数和合并小时数的对象模型为:

  public class StoreHours {
    public DayOfWeek DayOfWeek { get; set; }
    public TimeSpan OpenTime { get; set; }
    public TimeSpan CloseTime { get; set; }
  }
  public class MergedStoreHours {
    public DayOfWeek FirstDayOfWeek { get; set; }
    public DayOfWeek LastDayOfWeek { get; set; }
    public TimeSpan OpenTime { get; set; }
    public TimeSpan CloseTime { get; set; }
    public override string ToString() {
      var day = FirstDayOfWeek != LastDayOfWeek ? FirstDayOfWeek + "-" + LastDayOfWeek : FirstDayOfWeek.ToString();
      var timeRange = OpenTime != CloseTime ? OpenTime + "-" + CloseTime : "-";
      return day + " " + timeRange;
    }
  }