为了账号安全,请及时绑定邮箱和手机立即绑定

C#Sort和OrderBy比较

/ 猿问

C#Sort和OrderBy比较

慕的地6264312 2019-10-29 13:14:48

我可以使用Sort或OrderBy对列表进行排序。哪一个更快?两者都在使用相同的算法吗?


List<Person> persons = new List<Person>();

persons.Add(new Person("P005", "Janson"));

persons.Add(new Person("P002", "Aravind"));

persons.Add(new Person("P007", "Kazhal"));

1。


persons.Sort((p1,p2)=>string.Compare(p1.Name,p2.Name,true));

2。


var query = persons.OrderBy(n => n.Name, new NameComparer());


class NameComparer : IComparer<string>

{

    public int Compare(string x,string y)

    {

      return  string.Compare(x, y, true);

    }

}


查看完整描述

3 回答

?
Cats萌萌

为什么不测量它:


class Program

{

    class NameComparer : IComparer<string>

    {

        public int Compare(string x, string y)

        {

            return string.Compare(x, y, true);

        }

    }


    class Person

    {

        public Person(string id, string name)

        {

            Id = id;

            Name = name;

        }

        public string Id { get; set; }

        public string Name { get; set; }

    }


    static void Main()

    {

        List<Person> persons = new List<Person>();

        persons.Add(new Person("P005", "Janson"));

        persons.Add(new Person("P002", "Aravind"));

        persons.Add(new Person("P007", "Kazhal"));


        Sort(persons);

        OrderBy(persons);


        const int COUNT = 1000000;

        Stopwatch watch = Stopwatch.StartNew();

        for (int i = 0; i < COUNT; i++)

        {

            Sort(persons);

        }

        watch.Stop();

        Console.WriteLine("Sort: {0}ms", watch.ElapsedMilliseconds);


        watch = Stopwatch.StartNew();

        for (int i = 0; i < COUNT; i++)

        {

            OrderBy(persons);

        }

        watch.Stop();

        Console.WriteLine("OrderBy: {0}ms", watch.ElapsedMilliseconds);

    }


    static void Sort(List<Person> list)

    {

        list.Sort((p1, p2) => string.Compare(p1.Name, p2.Name, true));

    }


    static void OrderBy(List<Person> list)

    {

        var result = list.OrderBy(n => n.Name, new NameComparer()).ToArray();

    }

}

在我的计算机上,以“发布”模式编译时,该程序将打印:


Sort: 1162ms

OrderBy: 1269ms

更新:


正如@Stefan所建议的,这是对大列表进行较少排序的结果:


List<Person> persons = new List<Person>();

for (int i = 0; i < 100000; i++)

{

    persons.Add(new Person("P" + i.ToString(), "Janson" + i.ToString()));

}


Sort(persons);

OrderBy(persons);


const int COUNT = 30;

Stopwatch watch = Stopwatch.StartNew();

for (int i = 0; i < COUNT; i++)

{

    Sort(persons);

}

watch.Stop();

Console.WriteLine("Sort: {0}ms", watch.ElapsedMilliseconds);


watch = Stopwatch.StartNew();

for (int i = 0; i < COUNT; i++)

{

    OrderBy(persons);

}

watch.Stop();

Console.WriteLine("OrderBy: {0}ms", watch.ElapsedMilliseconds);

印刷品:


Sort: 8965ms

OrderBy: 8460ms

在这种情况下,看起来OrderBy表现更好。


UPDATE2:


并使用随机名称:


List<Person> persons = new List<Person>();

for (int i = 0; i < 100000; i++)

{

    persons.Add(new Person("P" + i.ToString(), RandomString(5, true)));

}

哪里:


private static Random randomSeed = new Random();

public static string RandomString(int size, bool lowerCase)

{

    var sb = new StringBuilder(size);

    int start = (lowerCase) ? 97 : 65;

    for (int i = 0; i < size; i++)

    {

        sb.Append((char)(26 * randomSeed.NextDouble() + start));

    }

    return sb.ToString();

}

产量:


Sort: 8968ms

OrderBy: 8728ms

仍然OrderBy更快


查看完整回答
反对 回复 2019-10-29
?
一只斗牛犬

不,它们不是相同的算法。对于初学者,LINQ OrderBy被记录为稳定的(即,如果两个项目相同Name,则它们将以其原始顺序出现)。


它还取决于您是否对查询进行缓冲还是对其进行多次迭代(除非对结果进行缓冲,否则LINQ-to-Objects将对per重新排序foreach)。


对于OrderBy查询,我也很想使用:


OrderBy(n => n.Name, StringComparer.{yourchoice}IgnoreCase);

(对{yourchoice}之一CurrentCulture,Ordinal或InvariantCulture)。


List<T>.Sort


此方法使用Array.Sort,后者使用QuickSort算法。此实现执行不稳定的排序;也就是说,如果两个元素相等,则可能不会保留其顺序。相反,稳定排序保留了元素相等的顺序。


Enumerable.OrderBy


此方法执行稳定的排序;也就是说,如果两个元素的键相等,则保留元素的顺序。相反,不稳定排序不会保留具有相同键的元素的顺序。分类; 也就是说,如果两个元素相等,则可能不会保留其顺序。相反,稳定排序保留了元素相等的顺序。


查看完整回答
反对 回复 2019-10-29
?
郎朗坤

达林·迪米特洛夫(Darin Dimitrov)的答案表明,这OrderBy比List.Sort面对已经分类的输入要快一些。我修改了他的代码,以便它反复对未排序的数据进行排序,并且OrderBy在大多数情况下会稍慢一些。


此外,该OrderBy测试用于ToArray强制对Linq枚举器进行枚举,但显然返回的类型(Person[])与输入类型(List<Person>)不同。因此,我使用ToList而不是重新运行了测试,ToArray并且得到了更大的不同:


Sort: 25175ms

OrderBy: 30259ms

OrderByWithToList: 31458ms

编码:


using System;

using System.Collections.Generic;

using System.Diagnostics;

using System.Linq;

using System.Text;


class Program

{

    class NameComparer : IComparer<string>

    {

        public int Compare(string x, string y)

        {

            return string.Compare(x, y, true);

        }

    }


    class Person

    {

        public Person(string id, string name)

        {

            Id = id;

            Name = name;

        }

        public string Id { get; set; }

        public string Name { get; set; }

        public override string ToString()

        {

            return Id + ": " + Name;

        }

    }


    private static Random randomSeed = new Random();

    public static string RandomString(int size, bool lowerCase)

    {

        var sb = new StringBuilder(size);

        int start = (lowerCase) ? 97 : 65;

        for (int i = 0; i < size; i++)

        {

            sb.Append((char)(26 * randomSeed.NextDouble() + start));

        }

        return sb.ToString();

    }


    private class PersonList : List<Person>

    {

        public PersonList(IEnumerable<Person> persons)

           : base(persons)

        {

        }


        public PersonList()

        {

        }


        public override string ToString()

        {

            var names = Math.Min(Count, 5);

            var builder = new StringBuilder();

            for (var i = 0; i < names; i++)

                builder.Append(this[i]).Append(", ");

            return builder.ToString();

        }

    }


    static void Main()

    {

        var persons = new PersonList();

        for (int i = 0; i < 100000; i++)

        {

            persons.Add(new Person("P" + i.ToString(), RandomString(5, true)));

        } 


        var unsortedPersons = new PersonList(persons);


        const int COUNT = 30;

        Stopwatch watch = new Stopwatch();

        for (int i = 0; i < COUNT; i++)

        {

            watch.Start();

            Sort(persons);

            watch.Stop();

            persons.Clear();

            persons.AddRange(unsortedPersons);

        }

        Console.WriteLine("Sort: {0}ms", watch.ElapsedMilliseconds);


        watch = new Stopwatch();

        for (int i = 0; i < COUNT; i++)

        {

            watch.Start();

            OrderBy(persons);

            watch.Stop();

            persons.Clear();

            persons.AddRange(unsortedPersons);

        }

        Console.WriteLine("OrderBy: {0}ms", watch.ElapsedMilliseconds);


        watch = new Stopwatch();

        for (int i = 0; i < COUNT; i++)

        {

            watch.Start();

            OrderByWithToList(persons);

            watch.Stop();

            persons.Clear();

            persons.AddRange(unsortedPersons);

        }

        Console.WriteLine("OrderByWithToList: {0}ms", watch.ElapsedMilliseconds);

    }


    static void Sort(List<Person> list)

    {

        list.Sort((p1, p2) => string.Compare(p1.Name, p2.Name, true));

    }


    static void OrderBy(List<Person> list)

    {

        var result = list.OrderBy(n => n.Name, new NameComparer()).ToArray();

    }


    static void OrderByWithToList(List<Person> list)

    {

        var result = list.OrderBy(n => n.Name, new NameComparer()).ToList();

    }

}


查看完整回答
反对 回复 2019-10-29

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信