C# List 定義及七種常用方法

1note-2527458

看完了以家人之名後,大叔該專心回來分享程式經驗了,大叔的工作寫C#程式也有四年多了,以前寫PHP時那種結合陣列(associative array)寫的很爽,現在用C#來工作,那種向量陣列(vector array)(C、C++、Java、C#…),事先就得宣告陣列大小,讓我有點不適應,你想想如果我要做一個以家人之名的演員陣列,那是不是我要先看完所有40集的電視後才能確定陣列的大小。

而在PHP中,我可以這樣寫,看到哪寫到哪:

$actors = array();
$actors['李尖尖'] = '譚松韻';
$actors['凌霄'] = '宋威龍';
$actors['賀子秋'] = '張新成';
print_r($actors);

在C# 裡其實也有類似PHP的結合陣列用法,就是使用List內建泛型類別,這有點像是不用宣告長度的陣列(Array),是沒有PHP那樣的直覺,需要稍微記一下 list這個單字,怕忘記可以將這篇文章加到我的最愛或是書籤中喔,以後有需要再點進來看。

什麼是 C# List?

命名空間:System.Collections.Generic

組件:mscorlib.dll, System.Collections.dll

表示可以依照索引存取的強類型物件列表。 提供搜尋、排序和管理清單的方法。

宣告:

//範例1:
List<T> mList = new List<T>();        //T爲列表中元素類型,現在以string類型作爲例子:
List<string> mList = new List<string>();

//範例2:
List<T> testList =new List<T> (IEnumerable<T> collection);  //以一個集合作爲參數創建List:
string[] temArr = { "李尖尖", "凌霄", "賀子秋", "李海潮", "凌和平", "齊明月", "唐燦", "杜鵑"};
List<string> testList = new List<string>(temArr);

List<T>裡的’T’是什麼?

List<T>是.NET Framework類別庫提供的泛型集合,將<>號裡面的T改成我們指定的型別,就會產生對應型別的集合,存入取出的過程都會是我們指定的型別,而不用每次都轉換成object影響到效能,編譯器也會知道我們指定成什麼型別,幫我們正確的進行型別檢查,免得執行時才發現選錯型別。

常用的屬性和方法

屬性

說明

Capacity

在不需要調整大小之下,取得或設定內部資料結構可以保存的項目總數。

Count

取得 List中包含的元素數目

Item

取得或設定索引中的項目

 

方法說明
Add將物件加入至 List的最後面
AddRange將特定集合的元素加入至 List的最後面
BinarySearch使用預設的比較子並傳回元素以零為起始的索引,來搜尋元素之整個排序的 List
Clear將所有元素從 List中移除
Contains判斷元素是否在 List中
Equals(Object)判斷指定的物件是否等於目前的物件。
Find擷取符合指定的元素,並傳回整個List中第一個相符的元素
Foreach在 List 的每一個元素上執行指定之動作。
IndexOf(T)搜尋指定的物件,並傳回整個 List 中第一個相符合元素的索引
Insert(Int32, T)將元素插入至 List 中指定的索引位置
InsertRange(Int32, IEnumerable<T>)將集合的元素插入位於指定索引的 List 中
Remove(T)從 List 移除特定物件的第一個相符合元素
RemoveAt(Int32)移除 List中指定索引的元素
RemoveRange(Int32, Int32)從 List 移除的元素範圍。
Sort使用預設比較子來排序整個 List 中的元素
TrimExcess將容量設為 List 中元素的實際數目,如果該數目小於臨界值。
TrueForAll判斷 List 中的每一個元素是否符合指定之述詞所定義的條件。

C# List的Add與AddRange方法

(1)Add:添加單個元素

List<string>  Soundtracks1= new List<string>();
Soundtracks1.Add("無畏");
Soundtracks1.Add("我會守在這裡");
Soundtracks1.Add("看不見的光");
Soundtracks1.Add("Like A Breeze");
Soundtracks1.Add("雨");

(2)AddRange:添加實作了界面IEnumerable<T>的一個泛型集合的所有元素到指定泛型集合末尾

string[] input = { "無畏", "我會守在這裡", "看不見的光" };
List<string> Soundtracks2 = new List<string>(input);
Soundtracks2.AddRange(dinosaurs);

用foreach 取出List 裡的值

// 可用foreach 取出List 裡的值
foreach(string myStringList in Soundtracks1)
{
        Console.WriteLine(myStringList);
}

程式輸出如圖:

// 取出單一個List 裡的值,如同陣列(Array)用法
// 無畏
Soundtracks2[0];

// 無畏
Soundtracks1[0];

下面的程式碼可以顯示List中第三個元素值
Console.WriteLine(Soundtracks1[2]);

如何使用 C# List 屬性

List 的 Capacity 代表集合的容量,Count 代表集合中的數量

隨著項目新增至 List 物件中,會重新配置內部陣列來增加容量。

重新配置的意義:

當加入新項目至 List 物件中時會去檢查 List 物件的 Capacity 與 Count 屬性值

當 Count 等於 Capacity,會自動重新配置內部陣列,並將新陣列的容量設為 Capacity 的倍數,並且在加入新項目以前,複製現有項目至新陣列,接著再將新項目加入。

成本:

      1.建立一個新的內部陣列

      2.將現有項目複製到新的內部陣列中

 當 List 物件中的項目多且項目資料量大時,重新配置的成本不小。

using System;
using System.Collections.Generic;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> Soundtracks1 = new List<string>();
            Soundtracks1.Add("無畏");
            Soundtracks1.Add("我會守在這裡");
            Soundtracks1.Add("看不見的光");
            Soundtracks1.Add("Like A Breeze");
            Soundtracks1.Add("雨");

            output(Soundtracks1);

            Soundtracks1.Add("If Rain");

            output(Soundtracks1);

            Soundtracks1.AddRange(new string[] {"My Everything","金鼎巷","杏林湾商务运营中心","莲花新城公交站947路" });

            output(Soundtracks1);

            Soundtracks1.AddRange(new string[] { "李尖尖", "凌霄", "賀子秋", "李海潮" });

            output(Soundtracks1);

            Console.ReadLine();

            //List count = 5, capacity = 8
            //List count = 6, capacity = 8
            //List count = 10, capacity = 16
            //List count = 14, capacity = 16
        }

        static void output(List<string> l)
        {
            Console.WriteLine("List count={0}, capacity={1}", l.Count, l.Capacity);
        }
    }
}

所以一般建議若項目數量是可預測的話,在建立 List<T> 物件時就設定 Capacity 大小,看到capacity的配置後,想要寫爽變動陣列,還是要考慮一下程式效能。

List<string>  testList  = new List<string>(32)

當 List<T> 物件項目加入完成後可使用 TrimExcess() 方法,或設定 Capacity  = Count 來減少不必要的記憶體空間,不過這些舉動也會引發重新配置。

但使用TrimExcess() 方法時會去檢查項目大於容量的 90%,就不會執行重新配置,避免為取得一點利益而產生昂貴的重新配置成本。

myList.TrimExcess();  //視情況重新配置

myList.Capacity = myList.Count;

C#中使用List集合的Insert方法在指定位置插入元素

在C#的List集合等資料型別變數中,我們可以使用List集合的Insert方法在指定的索引位置插入一個新元素,例如指定在List集合的第一個位置寫入一個新元素或者在List集合的中間某個位置插入一個新元素。List集合類的Insert方法的格式為ListObj.Insert(index,listNewObject),其中ListObj代表List集合物件,index代表要插入元素的位置,listNewObject表示插入值。

例如我們有個string型別的List集合actorsList,我們需要在actorsList集合的第一個位置插入”谭松韵”,則可以使用下列語法來實現:

actorsList.Insert(0,”谭松韵”);

InsertRange(int index,IEnumerable<T> items) 在index下標處插入一組元素,該下標以及之後的元素依次後移

下面的程式碼在第3個位置插入一個字串,在第2個位置插入一個集合

testList.Insert(3, "塗松岩"); 
// Collection of new authors 
string[] newAuthors = { "張晞臨", "孫銥", "何瑞賢" }; 
// Insert array at position 2 
testList.InsertRange(2, newAuthors);

C# 從集合中刪除元素

1.C# 使用 Remove() 方法從 List 中刪除元素

這個 Remove() 方法根據集合上的名稱刪除元素。此方法的語法如下:

ListName.Remove(“NameOfItemInList”);

範例:

using System;
using System.Collections.Generic;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> Soundtracks1 = new List<string>();
            Soundtracks1.Add("無畏");
            Soundtracks1.Add("我會守在這裡");
            Soundtracks1.Add("看不見的光");
            Soundtracks1.Add("Like A Breeze");
            Soundtracks1.Add("雨");           

            output(Soundtracks1);

            Soundtracks1.Add("If Rain");

            output(Soundtracks1);

            Soundtracks1.AddRange(new string[] {"My Everything","金鼎巷","杏林湾商务运营中心","莲花新城公交站947路" });

            output(Soundtracks1);

            Soundtracks1.AddRange(new string[] { "李尖尖", "凌霄", "賀子秋", "李海潮" });

            output(Soundtracks1);

            string[] temArr = { "李尖尖", "凌霄", "賀子秋", "李海潮", "凌和平", "齊明月", "唐燦", "杜鵑" };
            List<string> testList = new List<string>(temArr);
            testList.Insert(3, "塗松岩");
            // Collection of new authors 
            string[] newAuthors = { "張晞臨", "孫銥", "何瑞賢" };
            // Insert array at position 2 
            testList.InsertRange(2, newAuthors);

            Console.WriteLine("刪除前集合:");
            foreach (string myStringList in testList)
            {
                Console.WriteLine(myStringList);
            }

            Console.WriteLine();

            //Use of Remove() method
            testList.Remove("孫銥");
            Console.WriteLine("刪除後集合:");
            foreach (string myStringList in testList)
            {
                Console.WriteLine(myStringList);
            }

            Console.ReadLine();

            //List count = 5, capacity = 8
            //List count = 6, capacity = 8
            //List count = 10, capacity = 16
            //List count = 14, capacity = 16
        }

        static void output(List<string> l)
        {
            Console.WriteLine("List count={0}, capacity={1}", l.Count, l.Capacity);
        }
    }
}

2.C# 使用 RemoveAt() 方法從 List 中刪除元素

RemoveAt() 方法根據該元素的索引位置從 List 中刪除該元素。要知道 C# 中的索引以 0 開頭。因此,選擇索引位置時要小心。此方法的語法如下:

ListName.RemoveAt(Index);

範例:

using System;
using System.Collections.Generic;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> Soundtracks1 = new List<string>();
            Soundtracks1.Add("無畏");
            Soundtracks1.Add("我會守在這裡");
            Soundtracks1.Add("看不見的光");
            Soundtracks1.Add("Like A Breeze");
            Soundtracks1.Add("雨");    
            output(Soundtracks1);

            Soundtracks1.Add("If Rain");
            output(Soundtracks1);

            Soundtracks1.AddRange(new string[] {"My Everything","金鼎巷","杏林湾商务运营中心","莲花新城公交站947路" });
            output(Soundtracks1);

            Soundtracks1.AddRange(new string[] { "李尖尖", "凌霄", "賀子秋", "李海潮" });
            output(Soundtracks1);

            string[] temArr = { "李尖尖", "凌霄", "賀子秋", "李海潮", "凌和平", "齊明月", "唐燦", "杜鵑" };
            List<string> testList = new List<string>(temArr);
            testList.Insert(3, "塗松岩");
            // Collection of new authors 
            string[] newAuthors = { "張晞臨", "孫銥", "何瑞賢" };
            // Insert array at position 2 
            testList.InsertRange(2, newAuthors);
            Console.WriteLine("刪除前集合:");
            foreach (string myStringList in testList)
            {
                Console.WriteLine(myStringList);
            }
            Console.WriteLine();
            //Use of RemoveAt() method
            testList.RemoveAt(3);
            Console.WriteLine("刪除後集合:");
            foreach (string myStringList in testList)
            {
                Console.WriteLine(myStringList);
            }
            Console.ReadLine();

            //List count = 5, capacity = 8
            //List count = 6, capacity = 8
            //List count = 10, capacity = 16
            //List count = 14, capacity = 16
        }
        static void output(List<string> l)
        {
            Console.WriteLine("List count={0}, capacity={1}", l.Count, l.Capacity);
        }
    }
}

3.C# 使用 RemoveRange() 方法從 List 中刪除元素

在 C# 中,我們也可以同時刪除多個元素。為此,可以使用 RemoveRange() 方法。將要刪除的元素範圍作為引數傳遞給該方法。此方法的語法如下:

ListName.RemoveRange(int index, int count);

index 是要刪除的元素的起始索引,count 是要刪除的元素的數量。

範例:

using System;
using System.Collections.Generic;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> Soundtracks1 = new List<string>();
            Soundtracks1.Add("無畏");
            Soundtracks1.Add("我會守在這裡");
            Soundtracks1.Add("看不見的光");
            Soundtracks1.Add("Like A Breeze");
            Soundtracks1.Add("雨");
            output(Soundtracks1);

            Soundtracks1.Add("If Rain");
            output(Soundtracks1);

            Soundtracks1.AddRange(new string[] {"My Everything","金鼎巷","杏林湾商务运营中心","莲花新城公交站947路" });
            output(Soundtracks1);

            Soundtracks1.AddRange(new string[] { "李尖尖", "凌霄", "賀子秋", "李海潮" });
            output(Soundtracks1);

            string[] temArr = { "李尖尖", "凌霄", "賀子秋", "李海潮", "凌和平", "齊明月", "唐燦", "杜鵑" };
            List<string> testList = new List<string>(temArr);
            testList.Insert(3, "塗松岩");
            // Collection of new authors 
            string[] newAuthors = { "張晞臨", "孫銥", "何瑞賢" };
            // Insert array at position 2 
            testList.InsertRange(2, newAuthors);

            Console.WriteLine("刪除前集合:");
            foreach (string myStringList in testList)
            {
                Console.WriteLine(myStringList);
            }
            Console.WriteLine();

            //Use of RemoveRange() method
            testList.RemoveRange(3, 2);
            Console.WriteLine("刪除後集合:");
            foreach (string myStringList in testList)
            {
                Console.WriteLine(myStringList);
            }
            Console.ReadLine();

            //List count = 5, capacity = 8
            //List count = 6, capacity = 8
            //List count = 10, capacity = 16
            //List count = 14, capacity = 16
        }
        static void output(List<string> l)
        {
            Console.WriteLine("List count={0}, capacity={1}", l.Count, l.Capacity);
        }
    }
}

4.C#中List集合使用Clear方法清空集合

在C#中的List集合操作過程中,有時候需要清空List集合中的元素,將之重置為一個初始化的List集合,此時就可以使用到List集合的擴展方法Clear()方法,此方法將清空List集合中所有的元素,清空後List集合中的元素個數為0。

例如有個List<string>的集合list1,內部存儲7個字串,清空list1中的元素可使用下列語句:

List<string> list1 = new List<string>() { “李尖尖總是「善待這世界的尖銳」”, “譚松韻:「我很幸運,用童年治癒著自己的一生」”, “「李尖尖的人生哲學」”, “凌霄的成長,是選擇原諒”, “凌霄:「如果覺得做錯了,只有活著才能夠彌補」”, “賀子秋與童年和解,獲得媽媽的疼愛”, “家是永遠的避風港” };

list1.Clear();

C# List如何尋找元素?

有兩種方法:

1.使用IndexOf判斷元素第一次出現的索引位置

在C#的List集合操作中,有時候需要判斷元素在List集合中第一次出現的索引位置資訊,此時需要使用到List集合的IndexOf方法來判斷,如果元素存在List集合中,則IndexOf方法傳回所在的索引位置資訊,如果不存在則返回-1,IndexOf方法為int IndexOf(T item),item代表需要判斷的元素。

例如有個List<int>的集合list2,需要判斷數字17在list1集合中第一次出現的索引位置資訊:

List<int> list2 = new List<int>() { 5, 7, 3, 10,17, 15, 18, 20, 13, 2,12 };

var index=  list2.IndexOf(17);

計算結果為,index=4。

2.使用contains()方法,判斷元素是否包含特定值

語法:public bool Contains (T item);

範例:list2.Contains(17);

IndexOf 跟 contains在效能上的比較有滿多討論的,一般都說是IndexOf較好,測試範例如下:

            System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
            Random r = new Random();
            int value =r.Next(0, 100000000); //自己去變
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("==========");
                Console.WriteLine("value=" + value);
                       stopwatch.Start();
                       bool IsContainValue = (list.IndexOf(value) != -1);
                       stopwatch.Stop();
                       Console.WriteLine(stopwatch.Elapsed);
                      stopwatch.Reset();         

                      stopwatch.Start();
                      list.Contains(value);
                      stopwatch.Stop();
                      Console.WriteLine(stopwatch.Elapsed);              

                      stopwatch.Reset();
                      //Console.WriteLine("==========");
                      value = r.Next(0, 100000000); //自己去變
            }

但ITREAD上有篇《List集合的contains() ,indexOf的比較》卻提到是『contains()效率比較高』,卻沒有範例佐證,是有點詭異的說法。

C# List 如何排序?

List<T>作為集合,排序也是它的一個基本功能。List<T>可以通過Sort()對集合中的元素進行從小到大排序,同時Sort()還接收自定義比較器,這樣開發人員可以根據需要指定希望的比較方式。Sort()方法的4個版本的定義如下:

  1. Sort() 使用預設的比較子來排序在整個 List<T> 中的元素。
  2. Sort(IComparer<T>) 使用指定的比較子來排序在整個 List<T> 中的元素
  3. Sort(Int32, Int32, IComparer<T>) 使用指定的比較子對 List<T> 中某段範圍內的元素進行排序。
  4. Sort(Comparison<T>) 使用指定的 Comparison<T> 來排序在整個 List<T> 中的元素。

方法一、Sort()

該方法為系統預設的方法,單一參數時會預設進行升序排序。

            List<int> list1 = new List<int>();
            int[] animals = { 989, 515, 298,112,581 };
            list1.AddRange(animals);
            list1.Sort();
            foreach (int myintList in list1)
            {
                Console.WriteLine(myintList);
            }

List<string> list2 = new List<string>();
            list2.Add("譚松韻");
            list2.Add("宋威龍");
            list2.Add("張新成");
            list2.Add("塗松岩");
            list2.Add("張晞臨");
            list2.Sort();
            foreach (string myintList in list2)
            {
                Console.WriteLine(myintList);
            }

如果遇到多參數(Name、Age)排序時,需要對該預設方法進行修改。

如果沒有修改這個方法,會產生未處理的例外狀況

System.InvalidOperationException: ‘無法比較陣列中的兩個元素。’

ArgumentException: 至少一個物件必須實作 IComparable。

A:People類別繼承IComparable介面,實作CompareTo()方法

IComparable<T>:定義由值型別或類別實作的通用比較方法,為了在建立特定於型別的比較方法以對元素進行排序。

原理:自行實作的CompareTo()方法會在list.Sort()內部進行元素兩兩比較,最後實作排序

 

public class People : IComparable<People>
    {
        public int Age { get; set; }
        public string Name { get; set; }
        public People(string name, int age)
        {
            this.Name = name;
            this.Age = age;
        }
        public override string ToString()
        {
            string result = "";
            result = "[" + this.Name + "," + this.Age.ToString() + "]";
            return result;
        }
        // list.Sort()時會根據該CompareTo()進行自定義比較
        public int CompareTo(People other)
        {
            int x = this.Name.CompareTo(other.Name);
            if (x == 0)
            {
                if (this.Age > other.Age)
                    x = 1;
                else if (this.Age == other.Age)
                    x = 0;
                else
                    x = -1;
            }
            return x;
        }
    }

List<People> peopleList = new List<People>();
            peopleList.Add(new People("譚松韻", 31));
            peopleList.Add(new People("譚松韻", 22));
            peopleList.Add(new People("宋威龍", 22));
            peopleList.Add(new People("張新成", 26));
            peopleList.Add(new People("塗松岩", 45));
            peopleList.Add(new People("張晞臨", 55));
            peopleList.Add(new People("張晞臨", 65));
            peopleList.Sort();

            foreach (People myintList in peopleList)
            {
                Console.WriteLine(myintList.Name+","+ myintList.Age);
            }
            Console.ReadLine();

方法二、Sort(IComparer<T>)  

使用指定的比較子來排序在整個 List<T> 中的元素

跟上述繼承IComparable的方法不同,這個方法不可在People內繼承實作IComparer介面,而是需要新建比較方法類別進行介面實作

B.新建PeopleComparer類別、繼承IComparer介面、實作Compare()方法

原理:list.Sort()將PeopleComparer類別的元素作為引數,在內部使用Compare()方法進行兩兩比較,最終實作排序(注意:上述方法為CompareTo(),此處為Compare()方法)

    // 自定義比較方法類別
    class PeopleComparer : IComparer<People>
    {
        // 不同於CompareTo()單引數,此處為雙引數
        public int Compare(People x, People y)
        {
            if (x.Name != y.Name)
            {
                return x.Name.CompareTo(y.Name);
            }
            else if (x.Age != y.Age)
            {
                return x.Age.CompareTo(y.Age);
            }
            else return 0;
        }
    }

            // 客戶端
            // 傳入引數為自定義比較類別的元素  
            peopleList.Sort(new PeopleComparer());
            foreach (People myintList in peopleList)
            {
                Console.WriteLine(myintList.Name + "," + myintList.Age);
            }
            Console.ReadLine();

方法三、Sort(Int32, Int32, IComparer<T>)

使用指定的比較子對 List<T> 中某段範圍內的元素進行排序。

原理:List<T>.Sort(int index,, int count, IComparer<T> Comparer) 方法的引數:待排元素起始索引、待排元素個數、排序方法

            // 客戶端
            // 傳入引數為自定義比較類別的元素  
            peopleList.Sort(2,3,new PeopleComparer());
            foreach (People myintList in peopleList)
            {
                Console.WriteLine(myintList.Name + "," + myintList.Age);
            }
            Console.ReadLine();

方法四、Sort(Comparison<T>)

使用指定的 Comparison<T> 來排序在整個 List<T> 中的元素。

不同於上述繼承介面的方法,此方法的引數為 泛型委派 Comparison<T>

委派原型:public delegate int Comparison<in T>(T x,T y);

C:依照委派的使用方法,首先建立委派執行個體MyComparison,並繫結到自定義的比較方法PeopleComparison()上,最終呼叫list.Sort()時 將委派執行個體傳入

原理:list.Sort()根據傳入的委派方法,進行兩兩元素比較最後實作排序

        public static int PeopleComparison(People p1, People p2)
        {
            if (p1.Name != p2.Name)
            {
                return p1.Name.CompareTo(p2.Name);
            }
            else if (p1.Age != p2.Age)
            {
                return p1.Age.CompareTo(p2.Age);
            }
            else return 0;
        }

        static void Main(string[] args)
        {
            List<People> peopleList = new List<People>();
            peopleList.Add(new People("譚松韻", 31));
            peopleList.Add(new People("譚松韻", 22));
            peopleList.Add(new People("宋威龍", 22));
            peopleList.Add(new People("張新成", 26));
            peopleList.Add(new People("塗松岩", 45));
            peopleList.Add(new People("張晞臨", 55));
            peopleList.Add(new People("張晞臨", 65));
            //peopleList.Sort();
            // 客戶端
            // 傳入引數為自定義比較類別的執行個體  
            //peopleList.Sort(2,3,new PeopleComparer());
            //foreach (People myintList in peopleList)
            //{
            //    Console.WriteLine(myintList.Name + "," + myintList.Age);
            //}
            //Console.ReadLine();

            // 方法0 建立委派執行個體並繫結
            Comparison<People> MyComparison = PeopleComparison;
            // 傳入該執行個體實作比較方法
            peopleList.Sort(MyComparison);
            foreach (People myintList in peopleList)
            {
                Console.WriteLine(myintList.Name + "," + myintList.Age);
            }
            Console.ReadLine();
        }

此外,既然Comparison<T>是泛型委派,則完全可以用 Lambda表示式進行描述

           // Lambda表示式實現Comparison委託
            peopleList.Sort((p1, p2) =>
            {
                if (p1.Age != p2.Age)
                {
                    return p2.Age.CompareTo(p1.Age);
                }               
                else if (p1.Name != p2.Name)
                {
                    return p2.Name.CompareTo(p1.Name);
                }
                else return 0;
            });

            foreach (People myintList in peopleList)
            {
                Console.WriteLine(myintList.Name + "," + myintList.Age);
            }
            Console.ReadLine();

如何反轉C# List的元素?

在C#的List集合操作中,有時候需要對List集合中的元素的順序進行倒序反轉操作,此時就可使用到List集合中的Reverse方法來實現此功能,Reverse方法的簽名爲void Reverse(),此方法不需要任何參數,呼叫void Reverse()方法可將整個List集合中的元素的順序反轉過來。

A.Reverse()

反轉整個 List<T> 中項目的順序。

例如有個List集合list1中含有元素1至10,需要將這個list1集合中的元素反轉爲10至1的倒序順序排列可使用下列語句:

   List<int> list1 = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

   list1.Reverse();

B.Reverse(Int32, Int32)

反向指定範圍中項目的順序。

public void Reverse (int index, int count);

參數

index Int32 要反向範圍內之以零為起始的起始索引。

count Int32 要反向範圍中的項目數。

例外狀況

ArgumentOutOfRangeException

index 小於 0。

-或- count 小於 0。

ArgumentException

index 和 count 不代表 List<T> 中項目的有效範圍。

如何搜尋 C# List 的元素?

List<T>的BinarySearch方法搜尋一個排序 List中的元素並傳回以零為起始的索引項目

多載

A.BinarySearch(T):使用預設的比較子並傳回項目以零為起始的索引,來搜尋項目之整個排序的 List<T>。

B.BinarySearch(T, IComparer<T>):使用指定的比較子並傳回項目以零為起始的索引,來搜尋項目之整個排序的 List<T>。

C.BinarySearch(Int32, Int32, T, IComparer<T>):使用指定的比較子在已經過排序之 List<T> 內,搜尋某範圍的項目,並傳回該項目以零為起始的索引。

A.BinarySearch(T)方法

用法:public int BinarySearch (T item);

參數:item T 要尋找的物件。 參考類型的值可以是 null。

傳回:Int32

如果有找到 item,則為已排序的 List<T> 中 item 之以零為起始的索引,否則便為負數,此負數為大於 item 的下一個項目索引之位元補數,或者,如果沒有更大的項目,則為 Count 的位元補數。

例外狀況:InvalidOperationException

預設比較子 Default 找不到 IComparable<T> 泛型介面的實作或 T 類型的 IComparable 介面。

範例:

List<string> Geek = new List<string>();
            .Add("Coronavirus");
            Geek.Add("Election results");
            Geek.Add("Kobe Bryant");
            Geek.Add("Zoom");
            Geek.Add("IPL");

            Console.WriteLine("原來的List:");
            foreach (string g in Geek)
            {
                // prints original List
                Console.WriteLine(g);
            }
            Console.WriteLine("\n排序後的List:");
            // sort the List
            Geek.Sort();
            Console.WriteLine();
            foreach (string g in Geek)
            {
                // prints the sorted List
                Console.WriteLine(g);
            }
            Console.WriteLine("\n插入 India vs New Zealand:");

            // insert "India vs New Zealand" in the List
            //"India vs New Zealand" insert into its original 
            // position when the List is sorted
            int index = Geek.BinarySearch("India vs New Zealand");

            if (index < 0)
            {
                Geek.Insert(~index, "India vs New Zealand");
            }
            Console.WriteLine();

            foreach (string g in Geek)
            {
                // prints the sorted list
                // after inserting "EFGH"
                Console.WriteLine(g);
            }

輸出:

B.BinarySearch(T, IComparer<T>)方法

用法:public int BinarySearch (T item, System.Collections.Generic.IComparer<T>? comparer);

參數:

item T

要尋找的物件。 參考類型的值可以是 null。

comparer IComparer<T>

比較項目時所要使用的 IComparer<T> 實作。

-或- null 表示使用預設比較子 Default。

傳回:

Int32

如果有找到 item,則為已排序的 List<T> 中 item 之以零為起始的索引,否則便為負數,此負數為大於 item 的下一個項目索引之位元補數,或者,如果沒有更大的項目,則為 Count 的位元補數。

例外狀況:

InvalidOperationException

comparer 為 null,而且預設比較子 Default 找不到 IComparable<T> 泛型介面的實作或 T 類型的 IComparable 介面。

範例:

下列範例是來自微軟的,但因為翻譯怪怪的,所以我重新翻譯了一下,範例示範方法多載 Sort(IComparer<T>) 和方法多載 BinarySearch(T, IComparer<T>) 。

這個範例會針對名為 DinoCompare 的字串定義替代比較子實作 IComparer<string> (在Visual Basic是 IComparer(Of String),在 Visual C++是 IComparer<String^> ) 泛型介面,比較子的運作方式如下:首先,會測試比較 null 值的,而且會將 null 參考視為小於非 null。 其次,會比較字串長度,而較長的字串會被視為較大的。 第三,如果長度相等,則會使用一般字串比較。

字串的 List<T> 會被建立,並填入四個字串,四個字串沒有特定的順序。 list 隨即顯示,並使用替代比較子排序,然後再次顯示。

BinarySearch(T, IComparer<T>)然後會使用方法多載來搜尋不在 list 中的數個字串,採用替代比較子。 Insert方法是用來插入字串。 這兩個方法位於名為的函式中 SearchAndInsert ,以及使用BinarySearch(T, IComparer<T>)傳回的索引值做位元補數 (在 C # 和 Visual C++ 中是用 ~ 運算子,在Visual Basic中使用 Xor -1 運算子)取得負數,並使用它作為插入新字串的索引。

using System;
using System.Collections.Generic;

public class DinoComparer: IComparer<string>
{
    public int Compare(string x, string y)
    {
        if (x == null)
        {
            if (y == null)
            {
                // If x is null and y is null, they're
                // equal.
                return 0;
            }
            else
            {
                // If x is null and y is not null, y
                // is greater.
                return -1;
            }
        }
        else
        {
            // If x is not null...
            //
            if (y == null)
                // ...and y is null, x is greater.
            {
                return 1;
            }
            else
            {
                // ...and y is not null, compare the
                // lengths of the two strings.
                //
                int retval = x.Length.CompareTo(y.Length);

                if (retval != 0)
                {
                    // If the strings are not of equal length,
                    // the longer string is greater.
                    //
                    return retval;
                }
                else
                {
                    // If the strings are of equal length,
                    // sort them with ordinary string comparison.
                    //
                    return x.CompareTo(y);
                }
            }
        }
    }
}

public class Example
{
    public static void Main()
    {
        List<string> dinosaurs = new List<string>();
        dinosaurs.Add("Pachycephalosaurus");
        dinosaurs.Add("Amargasaurus");
        dinosaurs.Add("Mamenchisaurus");
        dinosaurs.Add("Deinonychus");
        Display(dinosaurs);

        DinoComparer dc = new DinoComparer();

        Console.WriteLine("\nSort with alternate comparer:");
        dinosaurs.Sort(dc);
        Display(dinosaurs);

        SearchAndInsert(dinosaurs, "Coelophysis", dc);
        Display(dinosaurs);

        SearchAndInsert(dinosaurs, "Oviraptor", dc);
        Display(dinosaurs);

        SearchAndInsert(dinosaurs, "Tyrannosaur", dc);
        Display(dinosaurs);

        SearchAndInsert(dinosaurs, null, dc);
        Display(dinosaurs);
    }

    private static void SearchAndInsert(List<string> list,
        string insert, DinoComparer dc)
    {
        Console.WriteLine("\nBinarySearch and Insert \"{0}\":", insert);

        int index = list.BinarySearch(insert, dc);

        if (index < 0)
        {
            list.Insert(~index, insert);
        }
    }

    private static void Display(List<string> list)
    {
        Console.WriteLine();
        foreach( string s in list )
        {
            Console.WriteLine(s);
        }
    }
}

/* This code example produces the following output:

Pachycephalosaurus
Amargasaurus
Mamenchisaurus
Deinonychus

Sort with alternate comparer:

Deinonychus
Amargasaurus
Mamenchisaurus
Pachycephalosaurus

BinarySearch and Insert "Coelophysis":

Coelophysis
Deinonychus
Amargasaurus
Mamenchisaurus
Pachycephalosaurus

BinarySearch and Insert "Oviraptor":

Oviraptor
Coelophysis
Deinonychus
Amargasaurus
Mamenchisaurus
Pachycephalosaurus

BinarySearch and Insert "Tyrannosaur":

Oviraptor
Coelophysis
Deinonychus
Tyrannosaur
Amargasaurus
Mamenchisaurus
Pachycephalosaurus

BinarySearch and Insert "":


Oviraptor
Coelophysis
Deinonychus
Tyrannosaur
Amargasaurus
Mamenchisaurus
Pachycephalosaurus
 */

C.BinarySearch(Int32, Int32, T, IComparer<T>)方法

用法:public int BinarySearch (int index, int count, T item, System.Collections.Generic.IComparer<T>? comparer);

參數:

index Int32 要搜尋範圍內之以零為起始的起始索引。

count Int32 搜尋範圍的長度。

item T 要尋找的物件。 參考類型的值可以是 null。

comparer IComparer<T> 比較項目時要使用的 IComparer<T> 實作,或 null 表示使用預設比較子 Default。

傳回:

Int32

如果有找到 item,則為已排序的 List<T> 中 item 之以零為起始的索引,否則便為負數,此負數為大於 item 的下一個項目索引之位元補數,或者,如果沒有更大的項目,則為 Count 的位元補數。例外狀況:

ArgumentOutOfRangeException index 小於 0。 -或- count 小於 0。

ArgumentException index 和 count 不代表 List<T> 中的有效範圍。

InvalidOperationException comparer 為 null,而且預設比較子 Default 找不到 IComparable<T> 泛型介面的實作或 T 類型的 IComparable 介面。

 

範例:

下列範例一樣取自微軟的範例,也是因為中文翻譯怪怪的,所以分享在這篇文章中,這個範例示範方法多載 Sort(Int32, Int32, IComparer<T>) 和方法多載 BinarySearch(Int32, Int32, T, IComparer<T>) 。

這個範例會針對名為 DinoCompare 的字串定義替代比較子,實作 IComparer<string>(Visual Basic 中以 IComparer(Of String),在 Visual C++ 則是以 IComparer<String^>  泛型介面中執行),比較子的運作方式如下:首先,會測試比較 null 值的,而且會將 null 參考視為小於非 null。 其次,會比較字串長度,而較長的字串會被視為較大的。 第三,如果長度相等,則會使用一般字串比較。

List<T>會建立字串的,並填入五個 herbivorous dinosaurs 和三個 carnivorous dinosaurs 的名稱。 在這兩個群組中,這些名稱不會有任何特定的排序次序。 隨即顯示 list、使用替代比較子排序 herbivores 的範圍,然後再次顯示 list。

BinarySearch(Int32, Int32, T, IComparer<T>)方法多載被用來搜尋 “Brachiosaurus” 的 herbivores 範圍。 找不到字串,且位補數 (在 C# 和 Visual C++ 中使用 ~ 運算子,而Visual Basic中使用 Xor -1方法)是負的, BinarySearch(Int32, Int32, T, IComparer<T>) 會用來做為插入新字串的索引。

 

using System;
using System.Collections.Generic;

public class DinoComparer: IComparer<string>
{
    public int Compare(string x, string y)
    {
        if (x == null)
        {
            if (y == null)
            {
                // If x is null and y is null, they're
                // equal.
                return 0;
            }
            else
            {
                // If x is null and y is not null, y
                // is greater.
                return -1;
            }
        }
        else
        {
            // If x is not null...
            //
            if (y == null)
                // ...and y is null, x is greater.
            {
                return 1;
            }
            else
            {
                // ...and y is not null, compare the
                // lengths of the two strings.
                //
                int retval = x.Length.CompareTo(y.Length);

                if (retval != 0)
                {
                    // If the strings are not of equal length,
                    // the longer string is greater.
                    //
                    return retval;
                }
                else
                {
                    // If the strings are of equal length,
                    // sort them with ordinary string comparison.
                    //
                    return x.CompareTo(y);
                }
            }
        }
    }
}

public class Example
{
    public static void Main()
    {
        List<string> dinosaurs = new List<string>();
        dinosaurs.Add("Pachycephalosaurus");
        dinosaurs.Add("Amargasaurus");
        dinosaurs.Add("Mamenchisaurus");
        dinosaurs.Add("Deinonychus");
        Display(dinosaurs);

        DinoComparer dc = new DinoComparer();

        Console.WriteLine("\nSort with alternate comparer:");
        dinosaurs.Sort(dc);
        Display(dinosaurs);

        SearchAndInsert(dinosaurs, "Coelophysis", dc);
        Display(dinosaurs);

        SearchAndInsert(dinosaurs, "Oviraptor", dc);
        Display(dinosaurs);

        SearchAndInsert(dinosaurs, "Tyrannosaur", dc);
        Display(dinosaurs);

        SearchAndInsert(dinosaurs, null, dc);
        Display(dinosaurs);
    }

    private static void SearchAndInsert(List<string> list,
        string insert, DinoComparer dc)
    {
        Console.WriteLine("\nBinarySearch and Insert \"{0}\":", insert);

        int index = list.BinarySearch(insert, dc);

        if (index < 0)
        {
            list.Insert(~index, insert);
        }
    }

    private static void Display(List<string> list)
    {
        Console.WriteLine();
        foreach( string s in list )
        {
            Console.WriteLine(s);
        }
    }
}

/* This code example produces the following output:

Pachycephalosaurus
Amargasaurus
Mamenchisaurus
Deinonychus

Sort with alternate comparer:

Deinonychus
Amargasaurus
Mamenchisaurus
Pachycephalosaurus

BinarySearch and Insert "Coelophysis":

Coelophysis
Deinonychus
Amargasaurus
Mamenchisaurus
Pachycephalosaurus

BinarySearch and Insert "Oviraptor":

Oviraptor
Coelophysis
Deinonychus
Amargasaurus
Mamenchisaurus
Pachycephalosaurus

BinarySearch and Insert "Tyrannosaur":

Oviraptor
Coelophysis
Deinonychus
Tyrannosaur
Amargasaurus
Mamenchisaurus
Pachycephalosaurus

BinarySearch and Insert "":


Oviraptor
Coelophysis
Deinonychus
Tyrannosaur
Amargasaurus
Mamenchisaurus
Pachycephalosaurus
 */

總結 

這篇文章說明如何使用 List<T> 類別來操作物件集合,還有分享如何新增、搜尋、排序及反轉排序 list 中的項目,這是最近大叔用C# 5年的心得,以上的分享或是翻譯有錯誤,也請各位告知或糾正,謝謝~~^^!

學 C# 敢找機電整合工程師的工作嗎?

Print Friendly, PDF & Email

感謝你看到這裡,很快就可以離開了,但最好的獎勵行動就是按一下幫我分享,感恩喔~

點我分享到Facebook

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料