首先申明一下,写此博文的目的是纪录一下,知识都是现成的,只是整理一下,为了让自己更容易看懂,比在其他地方更容易明白。因为它们太常用了,不忍心每次都去用那么长的时间查看MSDN,希望能在这里用理少的时间来理解并运用其用法。最终目标是减少从接触到能理解并使用的时间。
List<T>类型的查找操作Find与FindIndex

Point pt; List<Point> lstPs = new List<Point>(); for (int i = 0; i < 10; i++) { pt = new Point(i, i + 100); lstPs.Add(pt); } Point pp = lstPs.Find( delegate(Point p)//pp是结果Point,是查到的目标 { return p.X == 9;//这个是有目标的情况,如果没有这个X==9的这个点呢? }); Point ppNo = lstPs.Find(delegate(Point p) { return p.X == 1000;//如果队列中没有目标点,返回的是Point类型的默认值 }); Console.WriteLine("目标点是:"+pp); Console.WriteLine("没有发现目标点时得到的是默认值:" + ppNo); /* 返回结果如下: 目标点是:{X=9,Y=109} 没有发现目标点时得到的是默认值:{X=0,Y=0} */
结论:使用Find方法时要注意return 语句后面是bool类型的表达式,不是想当然的返回一个目标T类型,这里是Point类型。在List中有目标就查到目标,如果没有话就返回 T类型的默认值(default(T)可得到)。
FindIndex:

//名字 值 单位组合 nvu struct NameValueUnit { public string oname; public string ovalue; public string ounit; } //移除一个组合 public void RemoveByName(string name) { int index = -1; index = lstNVU.FindIndex(delegate(NameValueUnit nvu) { if (nvu.oname.Equals(name)) { return true; } else { return false; } }); lstNVU.RemoveAt(index); }
下面来看看FindAll的源码:

public List<T> FindAll(Predicate<T> match) { if( match == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); } Contract.EndContractBlock(); List<T> list = new List<T>(); for(int i = 0 ; i < _size; i++) { if(match(_items[i])) { list.Add(_items[i]); } } return list; }
主要依赖Predicate委托,那看一下这个委托:
public delegate bool Predicate<in T>(T obj);
传入一个用于判断满足条件的委托实例,就可以得到目标数据。很巧妙!。
List查询最近值

//List获取最近值原理。 //从List中寻找离number最近的数 list.Aggregate((x,y) => Math.Abs(x-number) < Math.Abs(y-number) ? x : y); //从源码上看是遍历所有元素,时间复杂度是O(n);
DataTable的使用
1、添加列
2、添加行
3、查找数据select方法的使用
4、获取列名

DataTable dtAll = new DataTable(); //下面建立列过程:分别添加名为ID的列,名为name的列,名为score的列,类型分别是long,string,float。 DataColumn dc = new DataColumn("ID", typeof(long)); dtAll.Columns.Add(dc); dc = new DataColumn("name", typeof(string)); dtAll.Columns.Add(dc); dc = new DataColumn("score", typeof(float)); dtAll.Columns.Add(dc); //为表添加行 DataRow dr = dtAll.NewRow(); dr[0] = 2009000;//其实是一个装箱过程,把int装箱为object dr[1] = "john"; dr[2] = 98.5; dtAll.Rows.Add(dr); dr = dtAll.NewRow(); dr[0] = 2009001; dr[1] = "Lucy"; dr[2] = 23.5; dtAll.Rows.Add(dr); DataRow[] drs = dtAll.Select("ID=2009000"); Console.WriteLine(drs[0][2]);//查找到的第一个人的分数score,结果是当然的98.5
几个需要注意的地方。第一、先添加列,而不是先添加行,在添加列后再补充每行;第二、向第n行的第m列添加数据时是一个装箱过程,取出目标数据时需要拆箱操作,一般是Convert.To***方法;第三、查寻时的过滤条件是string,语法是SQL相仿。
一个例子:查找条件不同时的结果。

DataTable dt = new DataTable(); for (int i = 0; i < 2; i++)//加两列 { DataColumn dc = new DataColumn(); if (i == 0) { dc.ColumnName = "we"; dc.DataType = typeof(int); } dt.Columns.Add(dc); } DataRow dr = dt.NewRow(); dr[0] = 99; dr[1] = "ddd"; dt.Rows.Add(dr); dr = dt.NewRow(); dr[0] = 80; dr[1] = "808080"; dt.Rows.Add(dr); string condition = "we>70 and we<" + 90; DataRow[] drs = dt.Select(condition); string tmp = drs[0][1].ToString();//能输出正常结果,根据条件condition的不同输出不同的结果 Console.WriteLine(tmp);
condition作为条件,使用SQL语法 .
要获取列名只用一条语句 :
1 dataTable.Columns[i].ColumnName;//得到第i列的列名
5、复制表结构
DataTable dt2 = dt1.Clone();//这样把表dt1的结构复制到表dt2中,但是不复制数据
6、得到DataTable的第begin行到第end行的数据,并返回一个过滤后的DataTable

/// <summary> /// 过滤第begin行到到end行之间的数据行 /// </summary> /// <param name="begin">开始行</param> /// <param name="end">结束行</param> /// <param name="oDT">源表</param> /// <returns></returns> public static DataTable DtSelectRows(int begin,int end, DataTable oDT) { if (oDT.Rows.Count < end) return oDT; DataTable NewTable = oDT.Clone(); DataRow[] rows = oDT.Select("1=1"); for (int i = begin; i <=end; i++) { NewTable.ImportRow((DataRow)rows[i]); } return NewTable; }
交换两行

public static DataTable SwapRow(int index1, int index2, DataTable dt) { DataRow dr = dt.NewRow(); dr.ItemArray = dt.Rows[index1].ItemArray; dt.Rows[index1].ItemArray = dt.Rows[index2].ItemArray; dt.Rows[index2].ItemArray = dr.ItemArray; return dt; }
DataView的一些用法
1、使用DataTable得到DataView时一个问题
原始有问题的代码如下:
1 DataView dvClass = booksClass.dtClass.DefaultView; 2 DataView dvChild = booksClass.dtClass.DefaultView; 3 dvClass.RowFilter="father='11'"; 4 dvChild.RowFilter = "father='22'";
这样做后,回头再看发现dvClass 和 dvChild的RowFilter是相同的,都是"father='22'";原来是因为dvClass dvChild引用了同一个实例。所以修改如下:
1 DataView dvChild = new DataView(booksClass.dtClass);// booksClass.dtClass.DefaultView; 2 dvClass.RowFilter = "father='11'"; 3 dvChild.RowFilter = "father='222'";
问题得以解决,两个DataView就变得独立了。
List的排序

private void InitSS() { List<MyStruct> lstStructs = new List<MyStruct>(); MyStruct ms1, ms2, ms3, ms4; ms1.age = 11; ms1.name = "aa"; lstStructs.Add(ms1); ms2.age = 23; ms2.name = "bb"; lstStructs.Add(ms2); ms3.age = 32; ms3.name = "dd"; lstStructs.Add(ms3); ms4.age = 4; ms4.name = "ss"; lstStructs.Add(ms4); textBox1.Text = string.Empty; textBox1.Text += "排序前: "; foreach (var item in lstStructs) { //Console.WriteLine(item.Id + "," + item.Name); textBox1.Text += item.age + ":" + item.name + " "; } lstStructs.Sort(delegate(MyStruct info1, MyStruct info2) { return info1.age.CompareTo(info2.age);//排序的关键 }); //Console.WriteLine("*****ListSort**********"); textBox1.Text += "排序后: "; foreach (var item in lstStructs) { //Console.WriteLine(item.Id + "," + item.Name); textBox1.Text += item.age + ":" + item.name + " "; } } private void btnSsort_Click(object sender, EventArgs e) { InitSS(); } } struct MyStruct { public int age; public string name; }
5、复制表结构
Dictionary
1、根据value得到key
1 var firstKey = dic.FirstOrDefault(q => q.Value == "2").Key; //get first key 其中q为一个键值对
两个List<>互相过滤数据
代码如下:

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace AboutList { class Program { static void Main(string[] args) { Student s1 = new Student { Age=10,Name="deng"}; Student s2 = new Student { Age = 15, Name = "li" }; Student s3 = new Student { Age = 18, Name = "张" }; Student s4 = new Student { Age = 20, Name = "王" }; Student s5 = new Student { Age = 25, Name = "李" }; List<Student> list1 = new List<Student> { s1, s2, s3, s4, s5 }; List<Student> list2 = new List<Student> { s1,s2}; //下面查找不在list2中,只在list1中的Student实例 List<Student> listRes = list1.FindAll(delegate(Student s) { int index = list2.FindIndex(delegate(Student ss) { return ss == s; }); if (index >= 0) { return false; } else { return true; } }); //输出看结果 foreach (var s in listRes) { Console.WriteLine("Name=" + s.Name + "; Age=" + s.Age); } Console.Read(); } } class Student { public int Age { get; set; } public string Name { get; set; } } }
List删除 重复数据

// 不能用foreach,因为迭代器是只读的 for (int i = 0; i < strs.Count; i++) { // 如果第一次出现的位置不等于最后一次出现的位置,则说明该元素不止出现一次 if (strs.IndexOf(strs[i]) != strs.LastIndexOf(strs[i])) { strs.RemoveAt(strs.LastIndexOf(strs[i])); } }
ddd
ddd
ddd
ddd
ddd
ddd