我希望将商店的开放时间相似的日子合并在一起。例如,如果我们有:
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的长列表,我该如何做到这一点。
答案 0 :(得分:2)
只需加入我的两分钱:
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 :(得分:1)
这是一种使用最小显式条件逻辑的方法。策略是:(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;
}
}