65.9K
CodeProject 正在变化。 阅读更多。
Home

索引集合(索引字典)

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4投票s)

2016年5月1日

CPOL

4分钟阅读

viewsIcon

16873

downloadIcon

409

带有键和索引的字典

引言

索引字典是索引集合系列中的第一个集合对象。普通的字典或哈希表通常能满足软件开发者的需求,但有时需要根据除键之外的其他附加属性来查找存储的项。这就像在数据库中,我们有一个行的键,并且为某些字段建立了索引。为此,我建议在字典中使用以下方法。

背景

想象一下您有一个人员字典,其中键是人员 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 的基本用法。

© . All rights reserved.