索引集合(索引字典)
带有键和索引的字典
引言
索引字典是索引集合系列中的第一个集合对象。普通的字典或哈希表通常能满足软件开发者的需求,但有时需要根据除键之外的其他附加属性来查找存储的项。这就像在数据库中,我们有一个行的键,并且为某些字段建立了索引。为此,我建议在字典中使用以下方法。
背景
想象一下您有一个人员字典,其中键是人员 ID。假设一个对象有名字和姓氏。按 ID 获取人员并不困难,但如果我们想按姓氏搜索人员呢?我们只有两种选择。第一种是:每次我们需要按姓氏查找人员时,就遍历字典并查找特定的姓氏。第二种是维护一个额外的字典,我们在其中存储一个指向原始字典姓氏的索引。
索引字典允许您一方面将其用作普通字典,另一方面定义索引属性。
重要提示 - 这是 Alpha 版本,它不是线程安全的。我计划在 IndexedCollections 命名空间中添加线程安全的索引字典,并开发其 Java 版本。
使用代码
您可以通过下载和编译解决方案来添加对索引字典的引用,或者通过 NuGet,使用 NuGet 包管理器控制台并执行以下命令:
Install-Package IndexedCollections
让我们以前面的人员为例,并使用索引字典来解决。假设我们有一个人员对象,其外观如下:
class Person
{
[Key]
public int Id { get; set; }
[Index]
public string LastName { get; set; }
[Index]
public string FirstName { get; set; }
public override string ToString()
{
return string.Format("{0} - {1},{2}", Id, LastName, FirstName);
}
}
Key - 属性定义类中的键属性。索引字典将查找此属性。如果找不到,它将抛出 NoKeyPropertyException 异常。
Index - 属性定义将用作索引的属性。这意味着,标记为字段的属性,字典可以通过它进行查询。有两种类型的索引:唯一索引和非唯一索引。唯一的区别是,出人意料的是,唯一属性的值在字典中应该是唯一的。
重要提示 - 所有标记为 Key 或 Index 的属性都必须实现 GetHashCode 方法,并且必须为不同的值返回不同的哈希码,为相同的值返回相同的哈希码。
现在,让我们定义字典:
IndexedDictionary<int,Person> people = new IndexedDictionary<int, Person>();
这很像声明一个普通字典。
int - 键的类型
Person - 值的类型
添加项
现在让我们添加一个项:
第一步: 创建一个 Person 实例
Person p1 = new Person(){Id = 1,First = “ John”, LastName = “Johnson”}
第二步: 将实例添加到字典
people.Add(p1);
我们没有显式传递键值,因为 Person
类的 Id
属性已经被标记为 **Key** 了。
向字典添加项的另一种方法是使用索引器(**[]**)。
people[p1.Id] = p1
获取数据
有两种不同的方法可以从索引字典中获取项。
1 - 使用索引器
Person p = people[1];
2 - 使用 GetByTemplate 方法
Person t = new Person(){Id = 1,FirstName = “John”};
Person [] p = people.GetByTemplate(t,LogicOperator.OR,true);
让我们看一下该方法的参数。第一个参数是我们要从中选择项的模板。索引字典会考虑标记为 Key 或 Index 的属性。如果我想仅通过索引属性匹配项,而忽略键,我必须将最后一个参数设置为 false,否则应为 true。这是默认参数,其默认值为 true。
第二个参数告诉字典如何执行项的匹配。OR - 表示提供的模板的任何已标记属性的匹配都会将项添加到结果集中。AND - 表示只有模板的所有已标记属性的匹配才会将项添加到结果集中。
AND_IGNORE_NULLS - 类似于 AND,但模板中值为空的已标记属性在匹配过程中将被忽略。
NOT - 至少有一个已标记属性值不相同的项将被添加到结果集中。
第三个参数告诉字典在匹配过程中是否包含键属性。如果此参数的值为 false,则在匹配过程中将忽略键属性。这是默认参数,其默认值为 true。
ForEach
索引字典实现了 IEnumerable 和 IEnumerator 接口,因此您绝对可以使用 foreach 语句进行迭代。
演示
该解决方案包含一个 Demo 项目。欢迎您运行并查看使用 IndexedDictionary 的代码。演示程序将人员存储在索引字典中。它存储他们的 ID(即字典键)、名字和姓氏(即索引)。
在上部框架中,您可以添加人员;在下部框架中,您可以查找和删除人员数据。欢迎您查看代码以了解 IndexedDictionary 的基本用法。