zoukankan      html  css  js  c++  java
  • 【类库】容器对象(List、DataTable、 DataView、Dictionary)

      首先申明一下,写此博文的目的是纪录一下,知识都是现成的,只是整理一下,为了让自己更容易看懂,比在其他地方更容易明白。因为它们太常用了,不忍心每次都去用那么长的时间查看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}
                  */
    List过滤

       结论:使用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);
            }
    FindIndex的使用

     下面来看看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;
            }
    FindAll

    主要依赖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);
    Select条件查找的使用

      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;
            }
    过滤第begin行到到end行之间的数据行

     交换两行

            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;
            }
        }
    }
    View Code

     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

  • 相关阅读:
    Graylog安装操作
    CF1012C Hills
    MySQL 加锁处理分析
    2.22考试
    int(1)和int(11)是否有区别?
    「LibreOJ NOI Round #1」验题
    MySQL一致性非锁定读
    [学习笔记]凸优化/WQS二分/带权二分
    MySQL latch小结
    [八省联考2018]林克卡特树lct——WQS二分
  • 原文地址:https://www.cnblogs.com/ddx-deng/p/3773077.html
Copyright © 2011-2022 走看看