C#数据容器

字符串(String)

构造
string str = "this is a string";  //使用字面值初始化;
str = new string(charr_array); //使用字符数组初始化;
str = new string(ch, n);  // 重复字符n次;

查找

tf = name.StartsWith("B")

正则表达式

Regex in System.Text.RegularExpressions
Regex.Match()

运算

String类有很多字符串修改方法,但是String对象本身是不会改变的;修改的结果由返回值返回,只能对变量进行重新复制,让它指向内存中的另一块区域。

要在源字符串直接做修改,则改用StringBuilder

拼接

使用+Concat方法,将对象的字符串表示(ToString())拼接形成一个字符串。

String.Concat(obj1,obj2,...);
String.Concat({obj1,obj2,....})

+运算符作用对象包含字符串时,作为拼接运算符。

字符串内插
string greeting = 'Hello', firstName = 'Bob';
string message = $"{greeting} {firstName}!";

可以同时使用逐字文本前缀符号 @ 和字符串内插 $ 符号。

格式化

使用格式声明对参数进行格式化并输出字符串。

String.Format("{0}...{1}...", arg1, arg2, ...)

支持格式化语法的类似方法包括:StringBuilder.AppendFormatConsole.WriteLineTextWriter.WriteLineDebug.WriteLine等。

复合格式声明

复合格式由参数索引,对齐声明和格式声明组成)。

{ index[,[+-]alignment][:formatString]}

多个格式项可以引用同一个参数,索引顺序与参数顺序无关。

对齐方式:alignment的绝对值代表了字符串的最小长度(字符串长度超过该值,则alignment无效);正值代表右对齐,负值代表左对齐,如果需要则填充空白。

不同类型的对象有不同的格式声明(格式声明在不同国家/语言有不同输出),其中: 标准数字格式包括:

格式名称说明
`Cc[n]`货币格式
`Dd[n]`整型数字
`Ee[n]`指数计数法
`Ff[n]`定点计数法
`Gg[n]`科学计数法
`Pp[n]`百分比
`Xx`十六进制整型

自定义数值格式:

标准日期和时间:

格式说明示例
d短日期6/15/2009
D长日期Monday, June 15, 2009
g短日期时间6/15/2009 1:45 PM
G长日期时间6/15/2009 1:45:30 PM

自定义日期和时间类型:获取日期时间中的字段

格式说明格式说明
y/yyyear(0-99/00-99)yyyyyear(0000-9999)
M/MMmonth(1-12/01-12)MMM/MMMMmonth name (short/long)
d/ddday-of-month
dddday-of-week, short (Mon)ddddday-of-week, long (Monday)
h/hhhour(1-12/01~12)H/HHhour(0-23/01-23)
m/mmminute(0-59/00-59)
s/sssecond(0-59/00-59)
t/ttAM/PM
g/ggA.D. or B.C.f/ff/fff/....x/.xx/.xxx/... seconds
Ktime zonez/zztimezone hour offset
:时间分隔符/日期分隔符

TimeSpan类型

枚举类型

  1. 标准数字格式字符串
  2. 标准日期和时间格式字符串
  3. 自定义日期和时间格式字符串
  4. 标准 TimeSpan 格式字符串
比较
bool Equals(string value, StringComparison comparisonType);
bool EndsWith(string value, comparisonType)

comparisonType:比较规则包括{Ordinal, OrdinalIgnoreCase }。当调用字符串比较函数如String.CompareString.EqualsString.IndexOf,应该总是使用带有comparisonType的函数指定比较规则。省略comparisonType,则该方法按照Ordinal规则(case-sensitive和culture-insensitive)进行比较。

StringBuilder

StringBuilder str = new StringBuilder();
str.Append(value);

编码

Encoding

数组

数组是用于存储多个同一类型变量的数据结构。数组是引用类型,派生于抽象基类Array类,所以数组也能当做类来使用。

声明

声明数组:

type[] arrayname;  // 1-D
type[,,,...] arrayname; // multi-dimension array

数组的类型由值类型type和“[]”指定的维数决定。数组元素的类型可以是基本类型也可以是引用类型(甚至可以是数组类型)。数组的维数根据“[]”中的“,”的个数确定,维数=逗号个数+1

数组初始化时的维度应该与数组声明一致,也可以将数组的声明和初始化放到一起。

type[] arrayname = new type[size];// initialize as default

数组在初始化时确定其维数和长度,且不能在实例存在期间修改。

数组的每个维度的长度或初始化列表可以省略,但两者不能同时省略:如果省略初始化列表则使用元素类型的默认值初始化数组;如果省略长度,则根据初始化列表元素的长度确定数组的长度;如果两者同时给出,则必须保证维数和长度声明与初始化列表一致

arrayname = new type[size]{initialize_list};
arrayname = new type[m,n]{{list1},{list2},...{listm}};
arrayname = new type[,]{{list1},{list2},...{listm}};
arrayname = {{list1},{list2},...{listm}};

锯齿数组

锯齿数组(或称为交错数组)的每个元素是数组。

type [,...][,...] arrayname;

声明中,第一个[,...]是锯齿数组的维度声明,第二个是锯齿数组元素的维度声明。虽然每个子数组的维数由声明确定,但是在初始化时,子数组之间各相应维度的长度可以各不相同,因此称为锯齿/交错数组。使用初始化列表赋值:

int[][,] jag_array = { // 使用初始化列表
    new int[,]{{1,2,3},{2,4,1}},
    new int[,]{{2,1},{4,2}},
    new int[,]{{1,3,5},{2,1,3},{3,4,5}}
    ...
};
int[][,] jag_array = new int[M][,]{...}

先使用new初始化交替数组本身,再初始化数组的每个元素:

int[][] jag_array = new int[M][];
for(int i=0; i<M; ++i){ //对每个元素逐个赋值
    jag_array[i] = new int[len_i];
}

可以定义高维的锯齿数组::

int[,][] multi_array = {
    {new int[]{1,2,3}, new int[]{2,1}},
    {new int[]{1,3}, new int[]{2,1,3}}
};

数组访问

下标

普通数组的访问方法是array[i,j,...]

交错数组的访问方法是array[i][j,k,...]

迭代

使用循环语句for

// 普通数组
for(int i = 0; i<M; ++i){
    for(int j=0; j<M; ++j){
        Console.Write("{0:G} ", array2d[i,j])
    }
}

使用foreach语句,高维数组视为一维数组迭代。

foreach(int x in array2d){
    Console.Write("{0:G} ", x)
}

foreach只能读元素,而不能修改数组。

数组维数和长度
array.Length;	// 数组的元素总数
array.GetLength(dim);  //数组的一个维度的长度;

容器

容器类型

泛型和非泛型容器

泛型容器(System.Collections.Generic)用于储存同一类型的元素,具有强类型要求,从而提供更好的类型安全以及更好的性能。

非泛型容器(System.Collections)存储的元素不要求特定的类型,所有元素都当作Object对象。非泛型集合(如 ArrayList)不建议使用,并且保留用于兼容性目的。大多数非泛型版本容器都不支持应用商店应用。

容器名泛型非泛型说明
列表List<T>ArrayList容器的大小可以增加或减小。提供查找、排序和修改等等方法。
链表LinkedList<T>
有序列表SortedList<Tk, Tv>SortedList使用ICompare接口根据对元素进行排序。
队列Queue<T>Queue具有先进先出(FIFO)操作规则。
Stack<T>Stack
映射Dictionary<Tk,Tv>HashTable基于键值或Hash值索引元素。
有序映射SortedDictionary<Tk, Tv>
集合HashSet<T>
有序集合SortedSet<T>

专用容器

System.Collections.Specialized

包含专用的强类型的结合。例如:链表字典,位向量,字符串容器。

并发容器

System.Collections.Concurrent

提供高效地线程安全的容器访问操作。当从多线程访问容器时,应该使用本空间中的对应容器类型代替System.Collections.GenericSystem.Collections中的类型。

容器公共特性

容器基于ICollectionIListIDictionary接口及其泛型版本。IListIDictionary派生自ICollection

容器接口包括:

  • ICollection<T>

  • IList<T>

  • IDictionary<T>

  • IComparer<T>

  • IEqualityComparer<T>

  • IEnumerator<T>

  • ISet<T>

枚举元素

容器类型继承IEnumerable/IEnumerable<T>,因此可以通过foreach语句进行枚举。继承自IEnumerable<T>的容器还可以通过LINQ进行查询。LINQ通常更简洁且可读性更强,提供筛选、排序以及分组能力,且能提高性能。

复制到数组

通过CopyTo方法将元素按照枚举顺序复制到一维数组中。

容量和计数

  • Capacity

    在不重新分配空间前,容器的容量。Capacity不应该设置为比Count小的值,否则引发异常(ArgumentOutOfRangeException)。

  • Count

    容器包含元素的数量。

一致的下界

元素从0起索引。Array可以自定义起始索引。

比较

Contains, IndexOf, LastIndexOf以及Remove等方法使用等式比较。泛型容器的比较方案:如果类型T继承了IEquatable\<T\>接口,则使用接口的Equals函数;否则使用Object.Equals

排序顺序

BinarySearchSort使用一个顺序比较器,用于比较容器的元素或与给定的值比较。

default comparer:依赖参与比较的对象至少有一个实现了IComparable接口。泛型类型的比较器方案:如果T实现了IComparable<T>接口,则默认比较器为IComparable<T>.CompareTo(T);如果T实现了IComparable接口,则默认比较器为IComparable.CompareTo(T);如果T没有实现以上接口,则必须显示提供比较器。

元素排序

  • SortedList/ SortedList<TKey, TValue>SortedDictionary<TKey, TValue>

实现IDictionary/``IDictionary<TKey, TValue>`接口,每个元素是key/value对。

元素根据ICompare/ICompare<T>接口排序。

每个类提供仅返回key或value的属性。

  • HashTable/Dictionary<TKey,TValue>

按key排序。

迭代器

迭代器用于容器的迭代访问操作。

使用foreach语句来调用迭代器。

访问容器的接口

容器相关操作

Queue

  • Dequeue/Enqueue

Stack

  • Push/Pop

    Peek

LINQ

You can write LINQ queries in C# with SQL Server databases, XML documents, ADO.NET Datasets, and any collection of objects that supports IEnumerable or the generic IEnumerable<T> interface.

All LINQ query operations consist of three distinct actions:

  1. Obtain the data source.

  2. Create the query.

  3. Execute the query.

数据源(Data Source)

LINQ数据源可以是支持IEnumerable<T>接口以及继承该接口的任何实例。支持IEnumerable<T>及其派生接口(如IQueryable<T>)的类型被称为可查询类型

Enumerable类提供一组用于查询实现IEnumerable<T>的对象的静态方法。

XElement

Northwnd

查询

查询语法:从对象序列中查询满足条件的对象,并返回筛选结果。

var seattleCustomers = from customer in customers
                       where customer.City == "Seattle"
			              [orderby customer.ID]
                       select customer.Name;   // or select customer

from指定数据源;where应用过滤条件;select语句指定返回元素的类型。

var localDistributors =
    from customer in customers
    join distributor in distributors on customer.City equals distributor.City
    select new { Customer = customer, Distributor = distributor.ID };

return a new type

var scoreQuery = from student in students
                 from score in student.Scores
                 where score > 90
                 select new { Last = student.LastName, score };

执行查询

延迟执行

查询变量本身只储存查询命令,当通过foreach语句对查询变量进行迭代时,才真正执行查询。

强制立即执行

统计函数:CountMaxAverageFirst

强制执行:ToList()ToArray();

在查询语句之后,立即使用foreach语句。

List

List实现的接口

IndexOfLastIndexOfRemove方法使用类型T的默认比较函数(EqualityComparer<T>.Default属性)判断相等。如果T实现了System.IEquatable<T>接口,则返回包含该接口的EqualityComparer,否则返回包含由T提供的Objects.EqualsObjects.GetHashCodeEqualityComparer

Contains方法使用默认的相等比较函数判断相等。如果T实现了IEquatable<T>接口,则调用IEquatabale.Equals方法,否则使用Object.Equals

SortBinarySearch使用类型T的默认的比较函数(Comparer<T>.Default属性)。如果T实现了IComparable<T>接口,则默认比较函数为IComparable<T>.CompareTo(T);否则如果实现了IComparable接口,则默认比较函数是IComparable.CompareTo();如果T没有实现比较接口,则必须显式提供比较委托。

List允许引用类型取值为null,以及重复元素。

ArrayList

ArrayList的容量是自动扩充的(类似于字符串,与一般数组不同);

ArrayList只能是一维的;

构造函数

List<T>()		//with default capacity
List<T>(Int32 Capacity)

属性

T this[int index] { get; set; }

按序号访问指定的元素。

方法

插入
void Add( T item );
void Insert( int index, T item )

Add添加元素到列表末尾。

Insert在指定序号处插入元素,指定的序号小于0或大于Count会引发异常(ArgumentOutOfRangeException)。

删除
bool Remove( T item );
int RemoveAll( Predicate<T> match );
void RemoveAt( int index )
void Clear();
void TrimExcess()

Remove移除出现的第一个指定元素,如果成功移除返回true;如果指定元素不在列表中或移除失败,返回false

RemoveAll移除满足条件的所有元素,并返回移除元素的数量。

RemoveAt移除指定位置的元素,指定的序号小于0或大于Count会引发异常(ArgumentOutOfRangeException)。

Clear移除列表中的所有元素。

TrimExcess将列表的容量缩小至元素实际数量。

查找
bool Contains( T item );
bool Exists( Predicate<T> match );
T Find( Predicate\<T\> match );  // FindLast
int FindIndex( Predicate\<T\> match ); // FindLastIndex
int IndexOf( T item );  // LastIndexOf
List<T> FindAll( Predicate<T> match );

Contains判断一个元素是否包含在列表中。(This method determines equality by using the default equality comparer, as defined by the object's implementation of the IEquatable<T>.Equals method forT (the type of values in the list).)

Exists判断是否存在匹配给定条件的元素。match定义了查找元素的条件。列表的元素分别被传递给match函数,当找到匹配元素时停止操作。

Find查找满足条件的元素并返回第一个元素。

FindAll查找所有满足条件的元素并返回。

FindIndex查找满足条件的元素并返回第一个元素序号。

IndexOf查找指定的元素,并返回第一个元素的序号。

排序
void Reverse()

反转整个列表的元素排列顺序。

void Sort()
void Sort( Comparison<T> comparison )
void Sort( IComparer<T> comparer )

使用comparison对列表排序。

使用comparer进行排序。

Dictionary

System.Collections in mscorlib

代表非一般性的键值对(key/value)的容器。每一个键值对储存在一个DictionaryEntry对象中。

每个键值对必须具有唯一的键名,实现类型可以决定是否允许键名为null。值可以是null且不要求唯一性。

IDictionary的实现类型分为三类:只读、固定长度、可变长度。

属性

按键名key访问元素:

Object this[ Object key] { get; set; }

键名和值

ICollection Keys { get; }
ICollection Values { get; }

值的顺序与Keys返回的键名的顺序对应。

DictionaryEntry定义字典的键值对。

Object Key { get; set; }
Object Value { get; set; }