【问题标题】:Querying a List of Objects查询对象列表
【发布时间】:2013-03-19 23:08:51
【问题描述】:

我目前有一个“Day”对象列表。 Day 的类定义包含两个字符串: -姓名 -小时

我需要做的是找到列表中具有相同小时数的所有 Day(s) 并将它们格式化为一个项目。

例如。

Sunday 8am - 9pm
Monday 8am - 10pm
Tuesday 8am - 10pm
Wednesday 8am -10pm
Thursday 9am - 10pm
Friday 9am - 11pm
Saturday 8am - 11pm

因此,周一周二和周三的营业时间相同。我需要从原始列表中创建一个新列表,如下所示:

Sunday 8am - 9pm
Mon-Wed 8am -10 pm
...
...

有没有使用 LINQ 的简单方法?

【问题讨论】:

  • 只应将连续天分组?
  • 只有上下班时间相同的日子

标签: c# linq microsoft-metro


【解决方案1】:

使用GroupConsecutive 扩展方法,您将在答案末尾找到,您可以执行以下操作:

List<Day> days = new List<Day>
{
    new Day { Name = "Sunday", Hours= "8am - 9pm" },
    new Day { Name = "Monday", Hours= "8am - 10pm" },
    new Day { Name = "Tuesday", Hours= "8am - 10pm" },
    new Day { Name = "Wednesday", Hours= "8am - 10pm" },
    new Day { Name = "Thursday", Hours= "9am - 10pm" },
    new Day { Name = "Friday", Hours= "8am - 11pm" },
    new Day { Name = "Saturday", Hours= "8am - 11pm" },
};

var query = from g in days.GroupConsequtive(d => d.Hours)
            select new {
                Name = g.Count() == 1 ? g.First().Name :
                       String.Format("{0}-{1}", g.First().Name.Substring(0, 3), g.Last().Name.Substring(0, 3)),
                Hours = g.Key
            };

枚举结果:

foreach (var item in query)            
    Console.WriteLine("{0} {1}", item.Name, item.Hours);

输出:

Sunday 8am - 9pm
Mon-Wed 8am - 10pm
Thursday 9am - 10pm
Fri-Sat 8am - 11pm

连续分组的扩展方法:

public static class LazyExtensions
{
    public static IEnumerable<IGrouping<TKey, TElement>> GroupConsecutive<TKey, TElement>(
        this IEnumerable<TElement> source, Func<TElement, TKey> keySelector)
    {
        if (!source.Any())
            yield break;

        var comparer = Comparer<TKey>.Default;
        Grouping<TKey, TElement> group = null;

        foreach (var item in source)
        {
            var key = keySelector(item);

            if (group == null)
                group = new Grouping<TKey, TElement>(key);

            if (comparer.Compare(group.Key, key) != 0)
            {
                yield return group;
                group = new Grouping<TKey, TElement>(key);
            }

            group.Elements.Add(item);
        }

        yield return group;
    }

    private class Grouping<TKey, TElement> : IGrouping<TKey, TElement>
    {
        public Grouping(TKey key)
        {
            Key = key;
            Elements = new List<TElement>();
        }

        public List<TElement> Elements { get; private set; }
        public TKey Key { get; private set; }

        public IEnumerator<TElement> GetEnumerator()
        {
            return Elements.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
}

它是如何工作的?它创建分组(自定义类,实现 IGrouping 接口)并将具有相同键值的连续元素添加到该组。如果新的键值到达,则返回分组。因此,所有序列都按连续的键值分组。

【讨论】:

  • @ZachJohnson 欢迎,实现通用的连续分组扩展很有趣:)
  • @DipenduPaul 谢谢!实际上最近我创建了better implementation,它更好地实现了组概念,并且不会在每次迭代时检查组是否为空:)
【解决方案2】:

这很接近你想要的:

        IList<Day> days = new List<Day>();
        days.Add(new Day { Name = "Sunday", Hours = "8am - 9pm" });
        days.Add(new Day { Name = "Monday", Hours = "8am - 10pm" });
        days.Add(new Day { Name = "Tuesday", Hours = "8am - 10pm" });
        days.Add(new Day { Name = "Wednesday", Hours = "8am - 10pm" });
        days.Add(new Day { Name = "Thursday", Hours = "9am - 10pm" });
        days.Add(new Day { Name = "Friday", Hours = "9am - 11pm" });
        days.Add(new Day { Name = "Saturday", Hours = "8am - 11pm" });
        var grouped = days.GroupBy(d => d.Hours).ToList();
        StringBuilder sb = new StringBuilder();
        foreach (var group in grouped)
        {
            sb.AppendFormat("{0}: {1}\n", group.Key, group.Select(g => g.Name).Aggregate((list, nextday) => list + ", " + nextday));
        }
        var table = sb.ToString();

输出是:

上午 8 点 - 晚上 9 点:周日

上午 8 点 - 晚上 10 点:周一、周二、周三

上午 9 点 - 晚上 10 点:星期四

上午 9 点 - 晚上 11 点:星期五

上午 8 点 - 晚上 11 点:星期六

【讨论】:

    【解决方案3】:
    List<Tuple<string,string>> days = new List<Tuple<string,string>>
    (
        new Tuple<string,string>[]
        {
            new Tuple<string,string>( "Sunday", "8am - 9pm" ),
            new Tuple<string,string>( "Monday", "8am - 10pm" ),
            new Tuple<string,string>( "Tuesday", "8am - 10pm" ),
            new Tuple<string,string>( "Wednesday", "8am - 10pm" ),
            new Tuple<string,string>( "Thursday ", "9am - 10pm" ),
            new Tuple<string,string>( "Friday", "9am - 11pm" ),
            new Tuple<string,string>( "Saturday ", "8am - 11pm" )
        }
    );
    
    ILookup<string,string> table = days.ToLookup( k => k.Item2, v => v.Item1 );
    
    table[ "8am - 9pm" ]; // Sunday
    table[ "8am - 10pm" ]; // Monday, Tuesday, Wednesday 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多