字典
- 字典表示一种非常复杂的数据结构,这种数据结构允许按照某个键来访问元素,字典也称为映射或散列表。
- 字典的主要特性是能根据键快速查找值。也可以自由添加和删除元素,这有点像List类,但没有在内存中移动后续元素的性能开销。
键的类型
字典示例
字典示例程序建立一个员工字典。该字典用EmployeeId对象来索引,储存在字典中的每个数据项都是一个Employee对象,该对象存储员工的详细数据。 ``` public class EmployeeIdException:Exception { public EmployeeIdException(string message):base(message){} } public truct EmployeeId:IEquatable { private readonly char _prefix; private readonly int _number;
public EmployeeId(string id) {
Contract.Requires<ArgumentNullException>(id!=null);
_prefix=(id.ToUpper())[0];
int numLength=id.Length-1;
try
{
_number=int.Parse(id.Substring(1,numLength>6?6:numLength));
}
catch (FormatException)
{
throw new EmployeeIdException("Invalid EmployeeId format");
}
} public override string ToString()=>_prefix.ToString()+$“{number,6:000000}”; public override int GetHashCode()=>(number^number<<16)*0x15051505; public bool Equals(EmployeeId other)=>(prefix==other?.prefix && number == other?.number); public override bool Equals(object obj)=>Equals((EmployeeId)obj);
public static bool operator ==(EmployeeId left,EmployeeId right)=>left.Equals(right);
public static bool operator !=(EmployeeId left,EmployeeId right)=>!(left==right);
}
- 由IEquatable<T>接口定义的Equals()方法比较两个EmployeeId对象的值,如果这两个值相同,它就返回true。除了实现IEquatable<T>接口中的Equals()方法之外,还可以重写Object类中的Equals()方法。
- Employee类是一个简单的实体类,该实体类包含员工的姓名、薪水和ID。构造函数初始化所有值,ToString()方法返回一个实例的字符串表示。ToString()方法的实现代码使用格式化字符串创建字符串表示,以提高性能
public class Employee {
private string _name;
private decimal _salary;
private readonly EmployeeId _id;
public Employee (EmployeeId id,string name,decimal salary)
{
_id=id;
_name=name;
_salary=salary;
}
public override string ToString()=>$"{id.ToString()}:{name,-20} {salary:C}";
}
- 示例应用程序的Main()方法中,创建一个新的Dictionary<TKey,TValue>实例,其中键是EmployeeId类型,值是Employee类型。构造函数指定31个元素的容量。注意容量一般是素数。但如果指定了一个不是素数的值,也不需要担心。Dictionary<TKey,Tvalue>类会使用传递给构造函数的整数后面紧接着的一个素数来指定容量。创建员工对象和ID后,就使用新的字典初始化语法把它们添加到新建的字典中
public static void Main() {
var employees=new Dictionary<EmployeeId,Employee>(31);
var idTony =new EmployeeId("c3755");
var tony =new Employee(idTony,"Tony Stewart",379025.00m);
var idCarl=new EmployeeId("F3547");
var carl=new Employee(idCarl,"Carl Edwards",403466.00m);
var idKevin=new EmployeeId("c3386");
var kevin=new Employee(idKevin,"Kevin Harwick",415261.00m);
var idMatt=new EmployeeID("F3323");
var matt=new Employee(idMatt,"Matt Kenseth",1589390.00m);
var idBrad=new EmployeeId("D3234");
var brad=new Employee(idBrad,"Brad Keselowski",322295.00m);
var employees=new Dictionary<EmployeeId,Employee>(31)
{
[idTony]=tony,
[idCarl]=carl,
[idKevin]=kevin,
[idMatt]=matt,
[idBrad]=brad
};
foreach(var employee inemployee.Values)
{
WriteLine(employee);
}
}
while (true) {
Write("Enter employee id(X to exit)");
var userInput=ReadLine();
userInput=userInput.ToUpper();
if(userInput == "X") break;
EmployeeId id;
try
{
id=new EmployeeId(userInput);
Employee employee;
if(!employee.TryGetValue(id,out employee))
{
WriteLine($"Employee with id{id} does not exist");
}
else
{
WriteLine(employee);
}
}
catch(EmployeeIdException ex)
{
WriteLine(ex.Message);
}
}
> Lookup类
- Dictionary<TKey,TValue>类支持每个键关联一个值。Lookup<TKey,TElement>类非常类似于Dictionary<TKey,TValue>类,但把键映射到一个值集合上。这个类在程序集System.Core中实现,用System.Linq名称空间定义。
- Lookup<TKey,TElement>类不能像一般的字典那样创建,而必须调用ToLookup()方法,该方法返回一个Lookup<TKey,TElement>对象。ToLookup()方法是一个扩展方法,它用于实现IEnumberable<T>接口的所有类。
- 下面例子中,填充一个Racer对象列表。因为List<T>类实现了IEnumberable<T>接口,所以可以在赛车手列表上调用ToLookup()方法。这个方法需要一个Func<TSource,Tkey>类的委托,Func<TSource,TKey>类定义了键的选择器。
var racers=new List(); racers.Add(new Racer(“Jacques”,“Villeneuve”,“Canada”,11)); racers.Add(new Racer(“Alan”,“Jones”,“Australia”,12)); racers.Add(new Racer(“Jackie”,“Stewart”,“United Kingdom”,27)); racers.Add(new Racer(“James”,“Hunt”,“United Kingdom”,10)); racers.Add(new Racer(“Jack”,“Brabham”,“Australia”,14));
var lookupRacers=racers.ToLookup(r=>r.Country); foreach (Racer r in lookupRacers(“Australia”)) {
WriteLine(r);
} ```
有序字典
- SortedDictionary是一个二叉搜索树,其中的元素根据键来排序。该键类型必须实现IComparablc接口。如果键的类型不能排序,则还可以创建一个实现了IComparer接口的比较器,将比较器用作有序字典的构造函数的一个参数。
- SortedDictionary和SortedList的功能类似。但因为SortedList实现为一个基于数组的列表,而SortedDictionary类实现为一个字典。他们有不同的特征。
- SortedList使用的内存比SortedDictionary少。
- SortedDictionary的元素插入和删除操作比较快。
- 在用已排好序的数据填充集合时,若不需要修改容量,SortedList比较快