是否有任何结构允许 BOTH 进行这些操作:
collection.TryGetValue(TKey, out TValue)
collection.TryGetKey(TValue, out TKey)
比O(n)更好的时间?
我的问题:
我基本上需要能够非常快速地检索键值或值的键,而不会重复内存(所以两个词典都是毫无疑问)。
非常重要的说明:所有键都是唯一的,所有值都是唯一的。有了这些信息我感觉应该可以在更好的时间内完成这项任务,而不仅仅是.TryGetValue
的O(1)和.TryGetKey
的O(n)。
修改
就我而言,我在strings
和ints
之间有一个映射。有大约650,000个键值对的文本及其ID。所以我基本上想要获取具有特定ID的字符串,以及某个字符串的ID。
答案 0 :(得分:3)
要比O(n)更好,你需要使用第二本字典。但是正如您所提到的那样,您正在使用结构并且关注内存使用情况,第二个字典具有结构的副本。
解决此问题的一种方法是将对象内部的struct值框中,然后共享两个词典中的盒装对象。如果你使用DictionaryBase
的继承,这实际上很容易实现。
public sealed class TwoWayDictionary<TKey, TValue> : DictionaryBase
{
Hashtable reverseLookup = new Hashtable();
public void Add(TKey key, TValue value)
{
this.Dictionary.Add(key, value);
}
public void Remove(TKey key)
{
this.Dictionary.Remove(key);
}
public bool TryGetValue(TKey key, out TValue value)
{
object lookup = Dictionary[key];
if (lookup == null)
{
value = default(TValue);
return false;
}
else
{
value = (TValue)lookup;
return true;
}
}
public bool TryGetKey(TValue value, out TKey key)
{
object lookup = reverseLookup[value];
if (lookup == null)
{
key = default(TKey);
return false;
}
else
{
key = (TKey)lookup;
return true;
}
}
//If OnInsertComplete or OnSetComplete raises a exception DictionaryBase will
// roll back the operation it completed.
protected override void OnInsertComplete(object key, object value)
{
reverseLookup.Add(value, key);
}
protected override void OnSetComplete(object key, object oldValue, object newValue)
{
if(reverseLookup.Contains(newValue))
throw new InvalidOperationException("Duplicate value");
if(oldValue != null)
reverseLookup.Remove(oldValue);
reverseLookup[newValue] = key;
}
protected override void OnRemoveComplete(object key, object value)
{
reverseLookup.Remove(value);
}
}
Dictionary
和reverseLookup
词典将共享相同的引用,因此与使用两个带有大型结构的强类型词典相比,它的内存占用量更小。
如果没有编写一个完整的Dictionary<TKey, TValue>
实现,它将两个内部存储桶集合用于键和值,而两个链接列表用于存储桶中的链,我认为您无法获得更好的结果。
答案 1 :(得分:0)
您可以为key
编写一些包装器,其中包含value
包装器的密钥和链接以及value
的包装器,它应包含值并链接到key
包装器。并使用两个不同的HashSet
s
在这种情况下,您可以避免重复内存。您只需要额外的内存链接。
答案 2 :(得分:-2)
Dictionary<string, string> types = new Dictionary<string, string>()
{
{"1", "one"},
{"2", "two"},
{"3", "three"}
};
var myValue = types.FirstOrDefault(x => x.Value == "one").Key;