【问题标题】:How to chain sorters with IEnumerable, with each sorter respecting the ordering produced by the previous one?如何使用 IEnumerable 链接排序器,每个排序器都尊重前一个排序器产生的排序?
【发布时间】:2013-02-09 20:29:21
【问题描述】:

基本上,我有一个小程序,我想在对象列表上执行一系列排序。每个排序都应该对对象的不同属性进行操作,并遵守前一个排序产生的排序。这是我目前所拥有的:

class Program
{
    static void Main(string[] args)
    {
        List<Person> people = new List<Person>();
        people.Add(new Person { Name = "John",   Age = 43 });
        people.Add(new Person { Name = "Ringo",  Age = 73 });
        people.Add(new Person { Name = "John",   Age = 32 });
        people.Add(new Person { Name = "Paul",   Age = 38 });
        people.Add(new Person { Name = "George", Age = 16 });
        people.Add(new Person { Name = "John",   Age = 80 });
        people.Add(new Person { Name = "Ringo",  Age = 22 });
        people.Add(new Person { Name = "Paul",   Age = 64 });
        people.Add(new Person { Name = "George", Age = 51 });
        people.Add(new Person { Name = "George", Age = 27 });
        people.Add(new Person { Name = "Ringo",  Age = 5 });
        people.Add(new Person { Name = "Paul",   Age = 43 });

        Print(Sort(people));
    }

    static IEnumerable<Person> Sort(IEnumerable<Person> people)
    {
        //order by name first, then order by age
        return people.OrderBy(p => p.Name).OrderBy(p => p.Age);
    }

    static void Print(IEnumerable<Person> people)
    {
        foreach (Person p in people)
            Console.WriteLine("{0} {1}", p.Name, p.Age);
    }

    class Person
    {
        public string Name {get; set;}

        public int Age { get; set; }
    }
}

这会产生以下输出:

林戈 5
乔治 16
林戈 22
乔治 27
约翰 32
保罗 38
约翰 43
保罗 43
乔治 51
保罗 64
林戈 73
约翰 80

但我希望它产生 这个 输出:

乔治 16
乔治 27
乔治 51
约翰 32
约翰 43
约翰 80
保罗 38
保罗 43
保罗 64
林戈 5
林戈 22
林戈 73

换句话说,我希望它按Name 排序,然后在每个Name“组”中按Age 执行本地化排序。显然,我目前的Sort() 方法并没有这样做,它只是执行两个链接的OrderBy

我可以用IEnumerable 做到这一点的最佳方法是什么?理想情况下,我希望解决方案能够扩展和支持尽可能多的链式排序,每个排序都会产生一组“组”,下一个排序器必须将其排序本地化到。

【问题讨论】:

  • 你看过 ThenBy() 来做链接吗?
  • 如前所述,您绝对应该选择ThenBy,但如果有兴趣:您是否注意到这两个 43 岁的人是按字母顺序排列的?这可能只是巧合,但实际上并非如此。这是因为Enumerable.OrderBy 执行的是稳定排序,这意味着任何两个具有相同年龄的记录都按照它们在底层枚举中出现的顺序进行排序,即按名称排序。这导致了另一种解决方案:.OrderBy(p =&gt; p.Age).OrderBy(p =&gt; p.Name)

标签: c# .net linq sorting


【解决方案1】:

尝试使用它应该在不破坏第一顺序的情况下重新排序

http://msdn.microsoft.com/en-us/library/bb534743.aspx

return people.OrderBy(p => p.Name).ThenBy(p => p.Age);

【讨论】:

  • 比我的建议更好,它使用字符串格式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-13
相关资源
最近更新 更多