清單不像陣列一樣要宣告長度,清單的長度是「可變的」。
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()可將該清單中的元素進行遞增排序:
※ 若該清單的元素資料型態是數字,比如int、short、float、double…等,那麼這個函式可將元素由小排到大。
※ 若該清單的元素資料型態是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進行排序。假設,排序的依據是person的age大小。
※ 範例(2-1):利用一個匿名函式(delegate),製作出一種「比較標準」來比較兩個person(p1,p2)之間的順序。若p1比p2大則此函式回傳1,若p1=p2則此回傳0,若p1比p2小則回傳-1。
由於排序的依據是person的age大小,故該匿名函式的內容就是去比較person的age大小。CompareTo函式是數字資料型態(int、short、float、double…等)所有的成員函式,用法例如:
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
留言列表