close

清單不像陣列一樣要宣告長度,清單的長度是「可變的」。

1. 清單的宣告:

(1) 不宣告初始值的宣告方式:

List<資料型態> 清單名稱 = new List<資料型態>();

在宣告清單後,這個清單的長度是0,也就是說沒有任何元素。要使用Add方法來為清單加入元素,如:

清單名稱.Add();    //這方法會將給加入清單的末尾成為清單中目前最後一個元素

之後,才能對清單的值進行呼叫與重設:

清單名稱[序數];    //呼叫該序數之元素的值

清單名稱[序數]=;    //重設該序數之元素的值為

例如:

List<int> A = new List<int>();

A.Add(3);

A.Add(5);

A.Add(7);

註:二維清單宣告方式:

List<List<資料型態>> 清單名稱= new List<List<資料型態>>();

(2) 宣告初始值的宣告方式:

List<資料型態> 清單名稱 = new List<資料型態>{ 值一, 值二, 值三… };

範例如:

List<int> scores = new List<int>{ 76, 23, 56,81,99 };

 

 

2. 清單所常用的成員及方法:

(1) 常用的成員:

清單名稱.Count:這是一個int,代表該清單的長度(元素數目)

(2) 常用的成員函式:

清單名稱.Add(變數):把這個變數給加入道清單之末尾,成為清單目前的最後一個元素。

清單名稱.AddRange(其他清單):把其他清單中的元素依序加入到清單之末尾。

清單名稱.Last():回傳該清單中的最後一個元素。

清單名稱.Clear():把這個清單中所有的元素都刪除。這樣一來,清單的長度會變成0

清單名稱.Insert(N,):將插入該清單中序數N的位置。原本序數N其及之後的元素,都會往後移順移排列。

清單名稱.Remove():該清單中若有元素的值為,就將此元素刪除,並回傳true,而後面的元素往前順移排列。否則回傳false

注意,該清單中若有兩個以上的元素的值為,此方法只會移除序數最小的那個元素。

清單名稱.RemoveAt(N):刪除該清單中,序數N的元素。而其後面的元素往前順移排列。

清單名稱.Reverse(N,L):將該清單中,自序數N開始連續共L個元素(包含序數N所對應的元素),給反向排列。

清單名稱.Sort():將該清單中的元素進行遞增排序。

清單名稱.Sum():若該清單的資料形態是int,則回傳一個int。若該清單的資料形態是double,則回傳一個double。代表該清單中所有元素的加總。

若該清單的資料形態是string或其他,則有可能發生錯誤。

清單名稱.GetType():回傳一個型態為System.Type的變數,表示該清單的資料型態。

清單名稱.IndexOf():回傳一個int。搜尋該清單中,是否有哪個元素的值是。若有則回傳其序數,若無則回傳-1。若有兩個以上元素的值是,則回傳序數最小者的序數。

清單名稱.GetRange(a,N):回傳該清單中,自第a個元素起,共N個元素(包含第a個元素)。所回傳的資料型態等於該清單本身的資料型態。要注意的是,回傳的清單僅只是一個參考位置,若該回傳的清單其中的元素遭到改變,則原本清單中的元素一樣會遭到改變。如以下程式碼:

public class person

{

    public int age;

    public string name;

    public person(int a, string n){ age = a; name = n; }

}

private void Form1_Load(object sender, EventArgs e)

{

    List<person> ps = new List<person>();

    person p1 = new person(10, ""); person p2 = new person(12, "");

    ps.Add(p1); ps.Add(p2);

    List<person> new_ps = ps.GetRange(0, 1);

    new_ps[0].age = 11;

    richTextBox1.Text = ps[0].age+"\r\n";

}

結果顯示:11

 

3. 清單的複製:

清單宣告式:List<資料型態> 清單名稱 = new List<資料型態>(); 之中,清單名稱實際上不是一個變數實體、而是一個指標。所以,若有以下程式碼:

List<資料型態> 清單名稱一 = new List<資料型態>();

List<資料型態> 清單名稱二 = 清單名稱一;

清單名稱一清單名稱二是指向同一個實體。例如:

List<int> A = new List<int>();

A.Add(5);

List<int> B = A;

B[0] = 10;

textBox1.Text += A[0].ToString();

則文字方塊中顯示出來的是10而非5

(1) 而若要將清單名稱一所指向的實體複製,然後讓清單名稱二指向該複製後的實體,要這樣寫:

List<資料型態> 清單名稱二 = 清單名稱一.ToList();

例如:

List<int> A = new List<int>();

A.Add(5);

List<int> B = A.ToList();

B[0] = 10;

textBox1.Text += A[0].ToString();

則文字方塊中顯示出來的就會是5了。

注意:上述方法不能用在二維清單及多維清單上。若用在二維清單上如:

List<List<int>> A = new List<List<int>>();

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

{

List<int> tmp = new List<int>();

for (int j = 0; j <= 1; j++)

{ tmp.Add(1); }   //將二維清單A的四個元素都設為1

A.Add(tmp);

}

 

List<List<int>> B = A.ToList();

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

{

for (int j = 0; j <= 1; j++)

{ B[i][j]=2; }    //將二維清單B的四個元素都設為2

}

textBox1.Text += A[0][0].ToString()+","+A[0][1].ToString()+","+A[1][0].ToString()+","+A[1][1].ToString();

則文字方塊中顯示出來的卻會是2,2,2,2了。這表示對B進行操作,卻同時也改變了A

若要複製二維清單,應逐項複製二維清單底下的一維清單,範例如下:

List<List<int>> A = new List<List<int>>();

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

{

List<int> tmp = new List<int>();

for (int j = 0; j <= 1; j++)

{ tmp.Add(1); }  //將二維清單A的四個元素都設為1

A.Add(tmp);

}

                            

List<List<int>> B = new List<List<int>>();

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

{

B.Add( A[i].ToList()); }  //逐項複製A的一維清單到B的一維清單

}

 

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

{

for (int j = 0; j <= 1; j++)

B[i][j] = 2; }    //將二維清單B的四個元素都設為2

}

textBox1.Text += A[0][0].ToString()+","+A[0][1].ToString()+","+A[1][0].ToString()+","+A[1][1].ToString();

則文字方塊中顯示出來的就會是1,1,1,1了。

 

4. 清單的排序:

(1) 清單名稱.Sort()可將該清單中的元素進行遞增排序:

若該清單的元素資料型態是數字,比如intshortfloatdouble…等,那麼這個函式可將元素由小排到大。

若該清單的元素資料型態是char,那麼此函式會依照元素的ASCII碼大小將之由小排到大。如:

List<char> ss = new List<char>() { 'a','g','e','t','b','z','c' };

ss.Sort();

則排序後清單呈現:{'a', 'b' , 'c' , 'e' , 'g' , 't' , 'z' }

若該清單的元素資料型態是string,那麼此函式會依照元素中第一個字元的ASCII碼大小將之由小排到大。若第一個字元的ASCII碼相同,則再比第二個字元的ASCII碼;若第二個字元的ASCII碼相同,則再比第三個字元的ASCII。如:

List<string> ss = new List<string>() { "sssabb", "abc", "abb", "bcb", "bca","a","b" };

ss.Sort();

則排序後清單呈現:{ "a", "abb", "abc", "b", "bca", "bcb", "sssabb" }

(2) 若清單中元素的資料型態是類別,則排序依據就應該是類別中某成員的大小,甚至更複雜的情況下,也可能是類別中某些成員經過某種演算法演算後的大小。此時可利用清單名稱.Sort(delegate),關於delegate,可參考「函式」教學。

在進行範例前先定義一個類別:

public class person

{

public string name;

public int age;

public double height;

public int money;

public person(string name_, int age_, double h, int m)

{ name = name_; age = age_; height = h; money = m; }

}

List<person> ps = new List<person>();

ps.Add(new person("", 18, 1.66, 5000));

ps.Add(new person("", 22, 1.76, 6000));

ps.Add(new person("", 10, 1.52, 2000));

ps.Add(new person("", 30, 1.63, 5500));

ps.Add(new person("", 21, 1.70, 1000));

ps.Add(new person("", 15, 1.32, 7000));

接著,要對一個ps進行排序。假設,排序的依據是personage大小。

※ 範例(2-1):利用一個匿名函式(delegate),製作出一種「比較標準」來比較兩個person(p1,p2)之間的順序。若p1p2大則此函式回傳1,若p1=p2則此回傳0,若p1p2小則回傳-1

由於排序的依據是personage大小,故該匿名函式的內容就是去比較personage大小。CompareTo函式是數字資料型態(intshortfloatdouble…)所有的成員函式,用法例如:

double a=1.0, b=1.5;

情況

a.CompareTo(b)的回傳值

a>b

1

a==b

0

a<b

-1

故,可利用CompareTo函式來建立匿名函式,排序的範例如:

ps.Sort(delegate(person p1, person p2) { return p1.age.CompareTo(p2.age); });

for (int i = 0; i < ps.Count; i++)  // 顯示結果

{richTextBox1.Text += ps[i].name + ", "+"age="+ps[i].age+"\r\n";}

執行後,richtextbox中顯示:

, age=10

, age=15

, age=18

, age=21

, age=22

, age=30

表示ps已依據age之大小由小排到大。若要改成由大排到小,可以用ps.Reverse()函式。若要更改排序依據(比如改成以height大小來排序),可將delegate中的

delegate(person p1, person p2) { return p1.age.CompareTo(p2.age); }

改成

delegate(person p1, person p2) { return p1.height.CompareTo(p2. height); }

要注意的是,delegate中的參數是person類別,而ps清單中的元素也是person類別。這表示,delegate中的參數,其變數型態,必須同於清單中元素的變數型態。

※ 範例(2-2):使用定義的函式來建立「比較標準」:

public static int person_comprasion(person p1, person p2)

{return p1.age.CompareTo(p2.age); }

 

ps.Sort(person_comprasion);  // 利用person_comprasion函式來排序

for (int i = 0; i < ps.Count; i++)  // 顯示結果

{richTextBox1.Text += ps[i].name + ", "+"age="+ps[i].age+"\r\n";}

執行後,richtextbox中顯示:

, age=10

, age=15

, age=18

, age=21

, age=22

, age=30

(3) 排序ps中的index

有時,程式設計師只想知道排序後的結果,但不想改變ps中的順序(也許這是因為ps原本的順序已被記錄下來以供其他用途,一旦更改後將會使該用途出錯),此時可以另立一個List<int> indexs代表ps中元素的index,使用以下範例將indexs排序,即可不影響ps中的順序:

List<int> indexs = new List<int>();

for (int i = 0; i < ps.Count; i++) { indexs.Add(i); }

indexs.Sort(delegate(int i1, int i2) { return ps[i1].age.CompareTo(ps[i2].age); });

for (int i = 0; i < indexs.Count; i++)   // 顯示結果

{ richTextBox1.Text += "index = " + indexs[i] + ", " + ps[indexs[i]].name + ", " + "age=" + ps[indexs[i]].age + "\r\n"; }

執行後,richtextbox中顯示:

index = 2, , age=10

index = 5, , age=15

index = 0, , age=18

index = 4, , age=21

index = 1, , age=22

index = 3, , age=30

 

 

上一篇:array

下一篇:arraylist

按此前往C#完整教學目錄

arrow
arrow

    埃伯 發表在 痞客邦 留言(0) 人氣()