C# での並べ替えは、コレクションの内容を特定の順序で配置するプロセスです。コレクションは、配列、リスト、またはその他のデータ グループです。コレクションには、複雑なタイプだけでなく単純なタイプの要素も含まれる場合があります。単純型は、整数、文字列、浮動小数点数などのコレクションである場合があります。複合型は、従業員、学生などのユーザー定義型のオブジェクトのコレクションである場合があります。複合型は、多くの場合入れ子になっており、オブジェクトには複数の属性がある場合があります。
例
C# には、コレクションを並べ替えるための組み込みメソッドが用意されています。配列、リスト、または汎用コレクションのいずれであっても、C# の Sort() メソッドは、提供された比較子に基づいて並べ替えることができます。内部的には、.Net 実装はクイックソート アルゴリズムを使用して C# でコレクションを並べ替えます。これについては、この記事の後続のセクションで詳しく説明します。
前に述べたように、.Net フレームワークはクイックソートのアプローチを使用して C# コレクション内の要素を並べ替えます。では、クイックソートとは何ですか?
クイックソートは分割統治戦略に従います。つまり、並べ替えアルゴリズムはピボット要素を選択し、ピボット要素に基づいて配列を分割します。ピボットより小さい要素はピボットの前に配置されます。ピボットより大きい要素はピボットの後に配置されます。これにより、ピボット要素が確実にソートされます。また、配列は、ピボットより小さい要素とピボットより大きい要素の 2 つに分割されます。次に、アルゴリズムは両方の配列に対して同じアプローチに従います。
これの図を以下に示します。
未ソート配列 – 18、5、16、23、50、32
ステップ 1 (ピボット = 32) – 18、5、16、23、32、50
ステップ 2a
未ソート配列 – 18、5、16、23
ピボット = 23
部分的にソートされた配列 – 18、5、16、23
ステップ 2b
未ソート配列 – 50
ピボット = 50
部分的にソートされた配列 – 50
ステップ 3a
未ソート配列 – 18、5、16
ピボット = 16
部分的にソートされた配列 – 5、16、18
ソートされた配列 – 5、16、18、23、32、50
したがって、クイックソートには、ピボットの選択と配列の分割という 2 つの重要なプロセスがあります。アルゴリズムの実装は、ピボットの選択によって異なります。これは、最初の要素、最後の要素、ランダムな要素、または配列の中央値のいずれかになります。分割が完了し、ピボットが正しい位置に配置されると、すべての要素が並べ替えられるまで、分割された配列に対してアルゴリズムが再帰的に呼び出されます。
C# でソートを行う場合、安定したクイックソートと不安定なクイックソートの概念が登場します。安定したクイックソートでは、2 つの要素が等しい場合、元の配列からの順序が保持されます。それ以外の場合は、クイックソートが不安定になります。 C# 実装では不安定なクイックソートを使用します。
記事のこのセクションでは、主に C# の 2 種類のコレクション (配列とリスト) に焦点を当てます。 C# が配列とリストを並べ替える方法について詳しく説明します。次のセクションでは、いくつかの例を挙げて説明していきます。
C# で配列を並べ替えるさまざまな方法を見てみましょう。
これはデフォルトの Sort() メソッドです。 Comparer がメソッドに明示的に渡されない場合、C# は昇順を使用して要素を配置します。
コード:
using System; public class Program { public static void Main() { String[] strArray = {"I", "Am", "Learning", "Array", "Sorting","In", "C#"}; int[] intArray = {23, 76, 12, 43, 90, 30}; Array.Sort(strArray); Array.Sort(intArray); Console.WriteLine("Sorted String Array:\n"); DisplayArray(strArray); Console.WriteLine("\n\n\nSorted Integer Array:\n"); DisplayArray(intArray); } static void DisplayArray(string[] arr) { foreach (string a in arr) { Console.Write(a + "\t"); } } static void DisplayArray(int[] arr) { foreach (int a in arr) { Console.Write(a + "\t"); } } }
出力:
Sort() メソッドに独自のカスタム Comparer を提供することもできます。これにより、デフォルトの比較子の代わりにカスタム比較子を使用するように C# コンパイラに指示されます。
カスタム比較子を作成するには、IComparer インターフェイスから Compare() メソッドを実装する必要があります。以下のコードは、要素を降順に並べ替える比較子を作成する方法を示しています。
クラスを作成し、それを IComparer インターフェイスから継承し、Compare() メソッドを実装して、要素を降順で比較するようにオーバーライドしました。
コード:
using System; public class DescendingComparer : System.Collections.IComparer { public int Compare(Object a, Object b) { return (new System.Collections.CaseInsensitiveComparer()).Compare(b, a); } } public class Program { public static void Main() { String[] strArray = {"I", "Am", "Learning", "Array", "Sorting","In", "C#"}; int[] intArray = {23, 76, 12, 43, 90, 30}; Array.Sort(strArray, new DescendingComparer()); Array.Sort(intArray, new DescendingComparer()); Console.WriteLine("Sorted String Array in Descending Order:\n"); DisplayArray(strArray); Console.WriteLine("\n\n\nSorted Integer Array in Desc Order:\n"); DisplayArray(intArray); } static void DisplayArray(string[] arr) { foreach (string a in arr) { Console.Write(a + "\t"); } } static void DisplayArray(int[] arr) { foreach (int a in arr) { Console.Write(a + "\t"); } } }
出力:
C# also provides a way to sort one array using key values from another array. The example below has key-value pairs of first names and last names of people. We would sort them by both first and last names using the Sort() method.
Code:
using System; public class Program { public static void Main() { String[] firstNames = {"Tom", "Jack", "Anna", "Veronica", "Jessica", "Mike"}; String[] lastNames = {"Phelps", "Anderson", "Spectre", "Clarke", "Williams", "Fonseca"}; Array.Sort(firstNames, lastNames); Console.WriteLine("Sorted by First Names:\n"); DisplayArray(firstNames, lastNames); Array.Sort(lastNames, firstNames); Console.WriteLine("\n\nSorted by Last Names:\n"); DisplayArray(firstNames, lastNames); } static void DisplayArray(string[] arr1, string[] arr2) { for (int i = 0; i < arr1.Length; i++) { Console.WriteLine(arr1[i] + " " + arr2[i]); } } }
Output:
Let us look at the different ways in which we can sort a list in C#.
Note – To use Lists in C#, including the library System.Collections.Generic.This is the default sort() method. if no comparer is explicitly passed to the method, c# uses the ascending order to arrange the elements.
Code:
public class Program using System.Collections.Generic; { public static void Main() { String[] strArray = {"I", "Am", "Learning", "Array", "Sorting", "In", "C#"}; List<string> strList = new List<string>(strArray); int[] intArray = {23, 76, 12, 43, 90, 30}; List<int> intList = new List<int>(intArray); strList.Sort(); intList.Sort(); Console.WriteLine("Sorted String List:\n"); DisplayList(strList); Console.WriteLine("\n\n\nSorted Integer List:\n"); DisplayList(intList); } static void DisplayList(List<string> myList) { foreach (string a in myList) { Console.Write(a + "\t"); } } static void DisplayList(List<int> myList) { foreach (int a in myList) { Console.Write(a + "\t"); } } }
Output:
We can also provide our own custom comparer to the sort() method. This would instruct the c# compiler to use the custom comparer instead of the default one.
To create a custom comparer, we need to implement the Compare() method from the IComparer interface. The code below demonstrates how to create a comparer that would sort the elements in descending order.
We created a class, inherited it from the IComparer interface, implemented the Compare() method and overrode it to compare the elements in descending order.
Code:
using System; using System.Collections.Generic; public class LengthComparer : IComparer<string> { public int Compare(string a, string b) { return (a.Length.CompareTo(b.Length)); } } public class DigitSumComparer : IComparer<int> { public int Compare(int a, int b) { int sum_a = 0; int sum_b = 0; while (a > 0) { sum_a += (a % 10); a /= 10; } while (b > 0) { sum_b += (b % 10); b /= 10; } return (sum_a.CompareTo(sum_b)); } } public class Program { public static void Main() { LengthComparer lc = new LengthComparer(); DigitSumComparer dsc = new DigitSumComparer(); String[] strArray = {"I", "Am", "Learning", "Array", "Sorting", "In", "C#"}; List<string> strList = new List<string>(strArray); int[] intArray = {23, 76, 12, 43, 90, 30}; List<int> intList = new List<int>(intArray); strList.Sort(lc); intList.Sort(dsc); Console.WriteLine("Sorted String List by Length:\n"); DisplayList(strList); Console.WriteLine("\n\n\nSorted Integer List by Sum of Digits:\n"); DisplayList(intList); } static void DisplayList(List<string> myList) { foreach (string a in myList) { Console.Write(a + "\t"); } } static void DisplayList(List<int> myList) { foreach (int a in myList) { Console.Write(a + "\t"); } } }
Output:
Complex List Types are user-defined lists. To be more precise, they are lists of objects of user-defined classes. Being user-defined, the objects are a mixture of various primitive types. It is difficult to sort a complex list type. C# compiler expects each complex class to inherit from the IComparable interface and define the method CompareTo(). This method contains the instructions on how to compare the elements of the list for sorting.
In the example below, we define a user-defined class of Employees and sort the Employee objects based on their IDs.
Code:
using System; using System.Collections.Generic; public class Employee : IComparable<Employee> { public int id {get;set;} public string name{get;set;} public double salary{get;set;} public int CompareTo(Employee e) { return this.id.CompareTo(e.id); } } public class Program { public static void Main() { List<Employee> emps = new List<Employee>(); emps.Add(new Employee() {id = 123, name = "Tom Phelps", salary = 20000.00}); emps.Add(new Employee() {id = 897, name = "Jack Anderson", salary = 40050.50}); emps.Add(new Employee() {id = 342, name = "Anna Spectre", salary = 31030.89}); emps.Add(new Employee() {id = 219, name = "Veronica Clarke", salary = 66333.66}); emps.Add(new Employee() {id = 642, name = "Jessica Williams", salary = 50505.05}); emps.Add(new Employee() {id = 923, name = "Mike Fonseca", salary = 76543.21}); Console.WriteLine("Original Employee List:\n"); DisplayList(emps); emps.Sort(); Console.WriteLine("\n\nSorted Employee List by IDs:\n"); DisplayList(emps); } static void DisplayList(List<Employee> emp) { foreach (Employee e in emp) { Console.WriteLine("Id: " + e.id + ", Name: " + e.name + ", Salary: " + e.salary); } } }
Output:
Now, the obvious question that comes to mind is that what if we want to sort the objects of Employee class based on some other property? This is possible. We would need to implement the IComparer interface. Let us take a look at the example below to understand.
Code:
using System; using System.Collections.Generic; public class Employee { public int id {get;set;} public string name{get;set;} public double salary{get;set;} } public class SortByName : IComparer<Employee> { public int Compare(Employee e1, Employee e2) { return e1.name.CompareTo(e2.name); } } public class SortBySalary : IComparer<Employee> { public int Compare(Employee e1, Employee e2) { return e1.salary.CompareTo(e2.salary); } } public class Program { public static void Main() { SortByName sbn = new SortByName(); SortBySalary sbs = new SortBySalary(); List<Employee> emps = new List<Employee>(); emps.Add(new Employee() {id = 123, name = "Tom Phelps", salary = 20000.00}); emps.Add(new Employee() {id = 897, name = "Jack Anderson", salary = 40050.50}); emps.Add(new Employee() {id = 342, name = "Anna Spectre", salary = 31030.89}); emps.Add(new Employee() {id = 219, name = "Veronica Clarke", salary = 66333.66}); emps.Add(new Employee() {id = 642, name = "Jessica Williams", salary = 50505.05}); emps.Add(new Employee() {id = 923, name = "Mike Fonseca", salary = 76543.21}); emps.Sort(sbn); Console.WriteLine("Sorted Employee List by Names:\n"); DisplayList(emps); emps.Sort(sbs); Console.WriteLine("\n\nSorted Employee List by Salaries:\n"); DisplayList(emps); } static void DisplayList(List<Employee> emp) { foreach (Employee e in emp) { Console.WriteLine("Id: " + e.id + ", Name: " + e.name + ", Salary: " + e.salary); } } }
Output:
So, this article covered in-depth on how to sort collections in C#. We focused majorly on Arrays and Lists since these two covers all the primitive types as well. Once the concept of Sorting in C# is very well understood, it becomes easy to implement sorting in other collections such as Enumerations, Dictionaries, etc. After completing this article, it is recommended to explore the MSDN documentation for more implementations of Sorting in C#.
以上がC# での並べ替えの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。