首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C#集团按类似时间存储开放日

C#集团按类似时间存储开放日
EN

Stack Overflow用户
提问于 2014-07-09 17:24:20
回答 1查看 551关注 0票数 0

我有一本字典,它储存一周中的每一天以及那天的开放/关闭时间。

代码语言:javascript
复制
Dictionary<string, string> hours = new Dictionary<string, string>();
hours.Add("M", String.Format("{0}-{1}", this.MondayOpen, this.MondayClosed));
hours.Add("T", String.Format("{0}-{1}", this.TuesdayOpen, this.TuesdayClosed));
hours.Add("W", String.Format("{0}-{1}", this.WednesdayOpen, this.WednesdayClosed));
hours.Add("Th", String.Format("{0}-{1}", this.ThursdayOpen, this.ThursdayClosed));
hours.Add("F", String.Format("{0}-{1}", this.FridayOpen, this.FridayClosed));
hours.Add("S", String.Format("{0}-{1}", this.SaturdayOpen, this.SaturdayClosed));
hours.Add("Su", String.Format("{0}-{1}", this.SundayOpen, this.SundayClosed));

我希望能够在字典中进行迭代,并根据相同的时间对天数进行分组。例如,我想像这样显示数据

代码语言:javascript
复制
M-Th 8:00 AM - 4:00 PM
F 8:00 AM - 6:00 PM
(leave Saturday and Sunday off if those days don't have open/close times)

我试过几种不同的方法,但都没能完全正确。这是我最近的尝试。

代码语言:javascript
复制
private string FormatHours2()
{
    StringBuilder sb = new StringBuilder();

    // add all of the hours to a dictionary
    Dictionary<string, string> hours = new Dictionary<string, string>();
    hours.Add("M", String.Format("{0}-{1}", this.MondayOpen, this.MondayClosed));
    hours.Add("T", String.Format("{0}-{1}", this.TuesdayOpen, this.TuesdayClosed));
    hours.Add("W", String.Format("{0}-{1}", this.WednesdayOpen, this.WednesdayClosed));
    hours.Add("Th", String.Format("{0}-{1}", this.ThursdayOpen, this.ThursdayClosed));
    hours.Add("F", String.Format("{0}-{1}", this.FridayOpen, this.FridayClosed));
    hours.Add("S", String.Format("{0}-{1}", this.SaturdayOpen, this.SaturdayClosed));
    hours.Add("Su", String.Format("{0}-{1}", this.SundayOpen, this.SundayClosed));

    // placeholder for the previous time range
    string prevValue = String.Empty;

    // inrun - indicates whether we are in a run of the same times.
    // firstTime - indicates whether this is the first time through the loop.
    bool inrun = false, firstTime = true;

    for (int i = 0; i < hours.Count; i++)
    {
        KeyValuePair<string, string> entry = hours.ElementAt(i);

        if (entry.Value != prevValue)
        {
            if (firstTime)
            {
                if (HasValue(entry.Value)) { sb.Append(entry.Key); }
            }
            else
            {
                if (!inrun)
                {
                    if (HasValue(prevValue)) { sb.Append(String.Format(" {0},", hours.ElementAt(i - 1).Value)); }

                    if (HasValue(entry.Value)) { sb.Append(entry.Key); }
                }
                else
                {
                    if (HasValue(prevValue))
                    {
                        sb.Append(String.Format("-{0} {1}", hours.ElementAt(i - 1).Key, hours.ElementAt(i - 1).Value));
                    }
                    if (HasValue(entry.Value)) { sb.Append(String.Format(",{0}", entry.Key)); }
                }
            }

            inrun = false;                    
        }
        else
        {
            inrun = true;
        }

        firstTime = false;
        prevValue = entry.Value;

        // if we're on the last iteration, write the value
        if (i == hours.Count() - 1)
        {
            if (inrun)
            {
                if (HasValue(entry.Value))
                {
                    sb.Append(String.Format("-{0} {1}", entry.Key, entry.Value));
                }
            }
            else
            {
                if (HasValue(prevValue))
                {
                    sb.Append(String.Format(" {0}", hours.ElementAt(i - 1).Value));
                }
            }
        }
    }


    return sb.ToString().TrimEnd(',');
}

这在所有的场景中都能很好的工作,除了当一周中的几天是关闭的时候,它不加逗号。

任何帮助都是非常感谢的。如果有人知道更好的方法,我愿意接受建议。我甚至不用用字典。

谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-07-09 21:20:05

您的代码很难阅读和维护,因为您正在尝试同时完成两件事:压缩数据(将天数合并为具有相同时间的组)和用描述构建文本。

我会把它分成两个步骤,添加一些LINQ,并对所有的部分进行重新组织。让我们从紧实问题开始。我们想要的是将列表分组成更小的集群,具有相同的工作时间。不幸的是,这里没有内置的LINQ方法。但我们当然可以写一个:

代码语言:javascript
复制
public static class EnumerableExtensions
{
    public static IEnumerable<TResult> Compact<T, TKey, TResult>(
        this IEnumerable<T> source, 
        Func<T,TKey> keySelector, 
        Func<TKey, IEnumerable<T>, TResult> resultSelector) 
    {
        if (!source.Any())
            yield break;
        var comparer = EqualityComparer<TKey>.Default;
        TKey previousKey = keySelector(source.First());
        List<T> group = new List<T>() { source.First() };
        foreach (var item in source.Skip(1))
        {
            TKey currentKey = keySelector(item);                
            if (!comparer.Equals(previousKey, currentKey))
            {
                yield return resultSelector(previousKey, group);
                group = new List<T>();
            }
            group.Add(item);
            previousKey = currentKey;
        }
        if (group.Any())
        {
            yield return resultSelector(previousKey, group);
        }
    }
}

这段代码应该放在某个助手库中,这样程序员就不会看到这些代码了。有了这个有用的方法,我们可以使用它:

代码语言:javascript
复制
var compact = hours.Compact(p => p.Value, 
                           (key, values) => new {
                               Hours = key,
                               Start = values.First().Key,
                               End = values.Last().Key
                           });

字典现在已经压缩(关于KeyValuePair<>.Value,意思是工作时间),而匿名对象的集合现在已经有了关于天的所有必要信息,您可以简单地用适当的格式对它们进行string.Join

代码语言:javascript
复制
Func<string, string, string> dayFormatter = 
    (first, second) => first == second ? first : string.Format("{0} - {1}", first, second);

var result = string.Join(", ", compact.Select(x => string.Format("{0} {1}",       
                                                      dayFormatter(x.Start, x.End),
                                                      x.Hours)));

注释:用于示例数据的,如:

代码语言:javascript
复制
string MondayOpen = "8:00 AM"; string MondayClosed = "4:00 PM";
string TuesdayOpen = "8:00 AM"; string TuesdayClosed = "4:00 PM";
string WednesdayOpen = "7:00 AM"; string WednesdayClosed = "3:00 PM";
string ThursdayOpen = "8:00 AM"; string ThursdayClosed = "4:00 PM";
string FridayOpen = "8:00 AM"; string FridayClosed = "4:00 PM";
string SaturdayOpen = "8:00 AM"; string SaturdayClosed = "2:00 PM";
string SundayOpen = "8:00 AM"; string SundayClosed = "2:00 PM";

Dictionary<string, string> hours = new Dictionary<string, string>();
hours.Add("M", String.Format("{0}-{1}", MondayOpen, MondayClosed));
hours.Add("T", String.Format("{0}-{1}", TuesdayOpen, TuesdayClosed));
hours.Add("W", String.Format("{0}-{1}", WednesdayOpen, WednesdayClosed));
hours.Add("Th", String.Format("{0}-{1}", ThursdayOpen, ThursdayClosed));
hours.Add("F", String.Format("{0}-{1}", FridayOpen, FridayClosed));
hours.Add("S", String.Format("{0}-{1}", SaturdayOpen, SaturdayClosed));
hours.Add("Su", String.Format("{0}-{1}", SundayOpen, SundayClosed));

上述代码产生:

代码语言:javascript
复制
`"M - T 8:00 AM-4:00 PM, W 7:00 AM-3:00 PM, Th - F 8:00 AM-4:00 PM, S - Su 8:00 AM-2:00 PM"`
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24660101

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档