如何实现多索引字典?

时间:2009-10-01 14:56:33

标签: c# generics collections dictionary thread-safety

基本上我想要像Dictionary< Tkey1,TKey2,TValue>这样的东西,但不是(正如我在其他问题中看到的那样)和AND中的键,但是在OR中。为了更好地解释:我希望能够在字典中找到只提供其中一个键的元素,而不是两者。

我还认为我们应该考虑线程安全性以及轻松扩展到Dictionary< Tkey1,TKey2,TKeyN,TValue>的能力。溶液...

11 个答案:

答案 0 :(得分:21)

我将使用这两个词典实现数据结构

Dictionary<TKey1, KeyValuePair<TKey2, TValue>> dict1;
Dictionary<TKey2, KeyValuePair<TKey1, TValue>> dict2;

这样,如果您获得1个密钥,则同时拥有值和其他密钥以便于删除和更新。

答案 1 :(得分:12)

所以你想要一个多索引词典,支持基于任何键的查找,并支持多个键的扩展?

也许您正在考虑错误的数据结构,请尝试使用KD-Tree。不可变的KD树将满足线程安全要求。

KD-tree比朴素Dictionary{Key1, Dictionary{Key2, Value}}方法有一些主要优势,即你可以在不知道Key1的情况下搜索基于Key2的所有字段。此外,KD树允许您搜索 near 其他键的键。例如,约会网站将人们分为几十个群体(吸烟者/非吸烟者,性别,宗教,生活方式,年龄,身高),然后根据您的查询返回最近的邻居。

这是一个C#和Java实现:

http://home.wlu.edu/~levys/software/kd/

答案 2 :(得分:5)

我会在这里走出去并且显得愚蠢,但你可以根据两个字典滚动你自己的字典。写入(即使使用锁定机制来确保线程安全)也不会太困难。我的意思是,有很多例子可以使用索引或密钥来访问集合。 (如会话)

相反,如果您的多个索引属于同一类型,则可以多次添加相同的项目。

Dictionary将支持具有GUID索引的内容,以及简单的名称索引“Joe” - 您必须记住将该项添加两次。

答案 3 :(得分:2)

您可以只使用常规字典并插入值两次,每个键一次。要删除,请删除这两个键。

上升空间:

  • 可以通过一次查找来搜索两个键。
  • 无需新代码。
  • 缩放到任意数量的键。

缺点:

  • 如果按键类型不同,则会失去类型安全性。
  • 无法迭代(key1,key2,value)元组。
  • 值显示两次,因此size()加倍。

答案 4 :(得分:2)

也许是一个选择:

按照约翰库格曼的建议,只需在同一个字典中添加两次。然后你保留第二个字典,将值映射到键集。

添加键值对时,只需将其正常添加到第一个词典中,然后从第二个词典中检索属于该值的键集并添加键。

Dictionary<TKey, TValue> dict1;
Dictionary<TValue, ICollection<TKey>> dict2;

通过从dict2中检索密钥集并从dict1逐个删除它来完成删除值。

键的数量是dict1.Count,值的数量是dict2.Count

答案 5 :(得分:1)

您是否考虑过持有两个词典,每个词一个?添加项目会将其添加到两者中。

删除意味着从两个词典中删除,并且需要两个键。要仅使用一个键删除,该项必须存储两个键。如果它还没有同时保存两个键,则可以将其包装在容纳对象和项目的容器对象中。

答案 6 :(得分:0)

两个字典,但不要复制每个字典。

您将拥有一个值字典和一个密钥字典。

当您调用add方法时,您将生成GUID并将其添加到密钥字典中。

然后,使用GUID作为值字典的键。

如果要添加两个键,您将使用相同的GUID将另一个项添加到键字典中。

当然这意味着每次查找都需要对数据进行两次检查,但即使您有50个相同值的密钥也不会更多。

根据keys表中的键查找guid,然后根据values表中的guid查找数据。

答案 7 :(得分:0)

我写了这样一本字典并将其发布在my blog上。它会给你一个很好的API:

DoubleKeyDictionary<int, string, string> books = new DoubleKeyDictionary<string, string, string>();
bookListEx.Add(1, “21/12/2009″, “Lord of the Rings - Fellowship of the Ring”); 

您也可以在两个字典上执行“Equals”,并在每个字典上执行“Equals”。

请注意,代码中至少有一个错误(在评论中发现)并且没有单元测试等。(是的!)我得到一些时间我会更新代码单元测试...

答案 8 :(得分:0)

多索引容器inspired by boost ??

怎么样?

看看CodeProject

答案 9 :(得分:0)

创建简单的类来存储Tkey1,TKey2,TValue,制作它们的列表并使用LINQ查询这样的结构将是一个选项。

答案 10 :(得分:0)

查看CodeProject上的这篇文章:http://www.codeproject.com/KB/recipes/multikey-dictionary.aspx

这显然是做多键字典的正确方法;)