C#中的多键词典(另一种)?
在此基础上,是否有一个简单的解决方案来拥有一个多键字典,其中任何一个键都可以单独用于标识值 即C#中的多键词典(另一种)?,c#,data-structures,C#,Data Structures,在此基础上,是否有一个简单的解决方案来拥有一个多键字典,其中任何一个键都可以单独用于标识值 即 多键字典foo; foo.Add(键1、键2、值); myValue=foo[key1]; //value==myValue foo.移除(键2); myValue=foo[key1];//返回无效、异常或null 当然,这是一种面向对象语言,您可以实现任何您想要的O。您将需要解决一些不明确的问题(如果TKey1和TKey2是相同的类型,那么会调用哪些方法呢?似乎详细介绍了一个相当不错的实现 C语言的
多键字典foo;
foo.Add(键1、键2、值);
myValue=foo[key1];
//value==myValue
foo.移除(键2);
myValue=foo[key1];//返回无效、异常或null
当然,这是一种面向对象语言,您可以实现任何您想要的O。您将需要解决一些不明确的问题(如果TKey1和TKey2是相同的类型,那么会调用哪些方法呢?似乎详细介绍了一个相当不错的实现
C语言的多键通用字典类#
MultiKeyDictionary是一个C#类
它包装并扩展了泛型
提供的字典对象
微软在.NET2.0及以上版本。这
允许开发人员创建泛型
价值观词典和参考文献
通过两个键而不是
只是微软提供的一个
通用规则的实施
字典。你可以看到我的
然而,关于CodeProject的文章(此处)
这段代码是最新的,有缺陷
免费的
目前.NET BCL中没有为这种类型的集合内置任何内容 我看到两种选择:
是,定义一个类,该类使用两个键将对象添加到内部哈希表中
public MyClass<k1, k2, T>: Dictionary<object, T>
{
private Dictionary<k1, k2> keyMap;
public new Add(k1 key1Val, k2 key2Val, T object)
{
keyMap.Add(key1Val, key2Val);
base.Add(k2, object)
}
public Remove(k1 key1Val)
{
base.Remove(keyMap[key1Val]);
keyMap.Remove(key1Val);
}
public Remove(k2 key2Val)
{
base.Remove(key2Val);
keyMap.Remove(key2Val);
}
}
公共MyClass:字典
{
专用字典键图;
公共新添加(k1 key1Val、k2 key2Val、T对象)
{
添加(key1Val,key2Val);
base.Add(k2,对象)
}
公共移除(k1键1VAL)
{
base.Remove(keyMap[key1Val]);
keyMap.Remove(key1Val);
}
公共移除(k2键2VAL)
{
底座。移除(键2val);
keyMap.Remove(key2Val);
}
}
您将无法为这两种类型定义重载,并且泛型系统不允许任意数量的类型(如方法允许参数)。因此,您将被一组定义了2、3、4等同步键的类所困扰。此外,还必须使用对象作为get和set的参数,使用运行时类型检查来模拟重载
此外,您只存储一个
字典,其他字典将是
,
,并将作为主字典的索引
它主要是锅炉板代码。您可能会发现我的实现是将其从Java重写为C#的良好基础。编程模型没有我喜欢的那么优雅,但它并不适合直接使用进行开发。相反,它位于一个缓存库后面,该库提供标准注释,以允许简洁的编码风格。通过使用Map接口,当它与自填充、过期和可收回的Map装饰器组合时,它提供了一个干净的组合模型。我相信有人会想出一个很好的编程接口,在可以接受的情况下,可以直接使用它来失去Map接口的好处。另一个简单(有效)的实现是使用“Pair
类型作为字典键,比如
Dictionary<Pair<TKey1, TKey2>, TValue> foo;
foo.Add(new Pair<TKey1, TKey2>(key1, key2), value);
字典foo;
foo.Add(新对(键1,键2),值);
Pair一致地实现了Equals
和GetHashCode
,因此您不需要求助于多级字典(它们更麻烦,可能也不太有效)
如果你需要三键词典,还有一个
三键词典。我试过了,效果很好(包括添加、删除和索引器)
公共类多键字典:字典
{
公共V本[K1 index1,K2 index2]
{
得到
{
返回此[新的KeyValuePair(index1,index2)];
}
设置
{
此[新的KeyValuePair(index1,index2)]=值;
}
}
公共布尔删除(K1 index1,K2 index2)
{
返回base.Remove(新的KeyValuePair(index1,index2));
}
公共无效添加(K1 index1,K2 index2,V值)
{
添加(新的KeyValuePair(index1,index2),value);
}
}
甚至我把它扩展到了4个值:
public class MultikeyDictionary<K1, K2, K3, V> : MultikeyDictionary<KeyValuePair<K1, K2>, K3, V>
{
public V this[K1 index1, K2 index2, K3 index3]
{
get
{
return base[new KeyValuePair<K1, K2>(index1, index2), index3];
}
set
{
base[new KeyValuePair<K1, K2>(index1, index2), index3] = value;
}
}
public bool Remove(K1 index1, K2 index2, K3 index3)
{
return base.Remove(new KeyValuePair<K1, K2>(index1, index2), index3);
}
public void Add(K1 index1, K2 index2, K3 index3, V value)
{
base.Add(new KeyValuePair<K1, K2>(index1, index2), index3, value);
}
}
公共类MultikeyDictionary:MultikeyDictionary
{
公共V本[K1 index1,K2 index2,K3 index3]
{
得到
{
返回基[newkeyvaluepair(index1,index2),index3];
}
设置
{
基[新的键值对(index1,index2),index3]=值;
}
}
公共布尔删除(K1 index1、K2 index2、K3 index3)
{
返回基。移除(新的KeyValuePair(index1、index2、index3);
}
公共无效添加(K1 index1、K2 index2、K3 index3、V值)
{
添加(新的KeyValuePair(index1,index2),index3,value);
}
}
享受
我发现这里的许多答案都不必要地复杂、性能较差或根本无法使用。最好的方法是将副键的KeyValuePair
和值作为任一词典的value
组合在一起。这使您只需对删除和更新操作进行一次查找。一个简单的实现:
public class DualDictionary<TKey1, TKey2, TValue> : IEnumerable<KeyValuePair<Tuple<TKey1, TKey2>, TValue>>
{
Dictionary<TKey1, KeyValuePair<TKey2, TValue>> _firstKeys;
Dictionary<TKey2, KeyValuePair<TKey1, TValue>> _secondKeys;
public int Count
{
get
{
if (_firstKeys.Count != _secondKeys.Count)
throw new Exception("somewhere logic went wrong and your data got corrupt");
return _firstKeys.Count;
}
}
public ICollection<TKey1> Key1s
{
get { return _firstKeys.Keys; }
}
public ICollection<TKey2> Key2s
{
get { return _secondKeys.Keys; }
}
public IEnumerable<TValue> Values
{
get { return this.Select(kvp => kvp.Value); }
}
public DualDictionary(IEqualityComparer<TKey1> comparer1 = null, IEqualityComparer<TKey2> comparer2 = null)
{
_firstKeys = new Dictionary<TKey1, KeyValuePair<TKey2, TValue>>(comparer1);
_secondKeys = new Dictionary<TKey2, KeyValuePair<TKey1, TValue>>(comparer2);
}
public bool ContainsKey1(TKey1 key)
{
return ContainsKey(key, _firstKeys);
}
private static bool ContainsKey<S, T>(S key, Dictionary<S, KeyValuePair<T, TValue>> dict)
{
return dict.ContainsKey(key);
}
public bool ContainsKey2(TKey2 key)
{
return ContainsKey(key, _secondKeys);
}
public TValue GetValueByKey1(TKey1 key)
{
return GetValueByKey(key, _firstKeys);
}
private static TValue GetValueByKey<S, T>(S key, Dictionary<S, KeyValuePair<T, TValue>> dict)
{
return dict[key].Value;
}
public TValue GetValueByKey2(TKey2 key)
{
return GetValueByKey(key, _secondKeys);
}
public bool TryGetValueByKey1(TKey1 key, out TValue value)
{
return TryGetValueByKey(key, _firstKeys, out value);
}
private static bool TryGetValueByKey<S, T>(S key, Dictionary<S, KeyValuePair<T, TValue>> dict, out TValue value)
{
KeyValuePair<T, TValue> otherPairing;
bool b = TryGetValue(key, dict, out otherPairing);
value = otherPairing.Value;
return b;
}
private static bool TryGetValue<S, T>(S key, Dictionary<S, KeyValuePair<T, TValue>> dict,
out KeyValuePair<T, TValue> otherPairing)
{
return dict.TryGetValue(key, out otherPairing);
}
public bool TryGetValueByKey2(TKey2 key, out TValue value)
{
return TryGetValueByKey(key, _secondKeys, out value);
}
public bool Add(TKey1 key1, TKey2 key2, TValue value)
{
if (ContainsKey1(key1) || ContainsKey2(key2)) // very important
return false;
AddOrUpdate(key1, key2, value);
return true;
}
// dont make this public; a dangerous method used cautiously in this class
private void AddOrUpdate(TKey1 key1, TKey2 key2, TValue value)
{
_firstKeys[key1] = new KeyValuePair<TKey2, TValue>(key2, value);
_secondKeys[key2] = new KeyValuePair<TKey1, TValue>(key1, value);
}
public bool UpdateKey1(TKey1 oldKey, TKey1 newKey)
{
return UpdateKey(oldKey, _firstKeys, newKey, (key1, key2, value) => AddOrUpdate(key1, key2, value));
}
private static bool UpdateKey<S, T>(S oldKey, Dictionary<S, KeyValuePair<T, TValue>> dict, S newKey,
Action<S, T, TValue> updater)
{
KeyValuePair<T, TValue> otherPairing;
if (!TryGetValue(oldKey, dict, out otherPairing) || ContainsKey(newKey, dict))
return false;
Remove(oldKey, dict);
updater(newKey, otherPairing.Key, otherPairing.Value);
return true;
}
public bool UpdateKey2(TKey2 oldKey, TKey2 newKey)
{
return UpdateKey(oldKey, _secondKeys, newKey, (key1, key2, value) => AddOrUpdate(key2, key1, value));
}
public bool UpdateByKey1(TKey1 key, TValue value)
{
return UpdateByKey(key, _firstKeys, (key1, key2) => AddOrUpdate(key1, key2, value));
}
private static bool UpdateByKey<S, T>(S key, Dictionary<S, KeyValuePair<T, TValue>> dict, Action<S, T> updater)
{
KeyValuePair<T, TValue> otherPairing;
if (!TryGetValue(key, dict, out otherPairing))
return false;
updater(key, otherPairing.Key);
return true;
}
public bool UpdateByKey2(TKey2 key, TValue value)
{
return UpdateByKey(key, _secondKeys, (key1, key2) => AddOrUpdate(key2, key1, value));
}
public bool RemoveByKey1(TKey1 key)
{
return RemoveByKey(key, _firstKeys, _secondKeys);
}
private static bool RemoveByKey<S, T>(S key, Dictionary<S, KeyValuePair<T, TValue>> keyDict,
Dictionary<T, KeyValuePair<S, TValue>> valueDict)
{
KeyValuePair<T, TValue> otherPairing;
if (!TryGetValue(key, keyDict, out otherPairing))
return false;
if (!Remove(key, keyDict) || !Remove(otherPairing.Key, valueDict))
throw new Exception("somewhere logic went wrong and your data got corrupt");
return true;
}
private static bool Remove<S, T>(S key, Dictionary<S, KeyValuePair<T, TValue>> dict)
{
return dict.Remove(key);
}
public bool RemoveByKey2(TKey2 key)
{
return RemoveByKey(key, _secondKeys, _firstKeys);
}
public void Clear()
{
_firstKeys.Clear();
_secondKeys.Clear();
}
public IEnumerator<KeyValuePair<Tuple<TKey1, TKey2>, TValue>> GetEnumerator()
{
if (_firstKeys.Count != _secondKeys.Count)
throw new Exception("somewhere logic went wrong and your data got corrupt");
return _firstKeys.Select(kvp => new KeyValuePair<Tuple<TKey1, TKey2>, TValue>(Tuple.Create(kvp.Key, kvp.Value.Key),
kvp.Value.Value)).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
公共类双字典:IEnumerable
{
字典第一键;
字典(附键),;
公共整数计数
{
得到
{
如果(_firstKeys.Count!=_secondKeys.Count)
抛出新异常(“某个地方逻辑出错,数据损坏”);
返回_firstKeys.Count;
}
}
公共I
public class MultikeyDictionary<K1, K2, K3, V> : MultikeyDictionary<KeyValuePair<K1, K2>, K3, V>
{
public V this[K1 index1, K2 index2, K3 index3]
{
get
{
return base[new KeyValuePair<K1, K2>(index1, index2), index3];
}
set
{
base[new KeyValuePair<K1, K2>(index1, index2), index3] = value;
}
}
public bool Remove(K1 index1, K2 index2, K3 index3)
{
return base.Remove(new KeyValuePair<K1, K2>(index1, index2), index3);
}
public void Add(K1 index1, K2 index2, K3 index3, V value)
{
base.Add(new KeyValuePair<K1, K2>(index1, index2), index3, value);
}
}
public class DualDictionary<TKey1, TKey2, TValue> : IEnumerable<KeyValuePair<Tuple<TKey1, TKey2>, TValue>>
{
Dictionary<TKey1, KeyValuePair<TKey2, TValue>> _firstKeys;
Dictionary<TKey2, KeyValuePair<TKey1, TValue>> _secondKeys;
public int Count
{
get
{
if (_firstKeys.Count != _secondKeys.Count)
throw new Exception("somewhere logic went wrong and your data got corrupt");
return _firstKeys.Count;
}
}
public ICollection<TKey1> Key1s
{
get { return _firstKeys.Keys; }
}
public ICollection<TKey2> Key2s
{
get { return _secondKeys.Keys; }
}
public IEnumerable<TValue> Values
{
get { return this.Select(kvp => kvp.Value); }
}
public DualDictionary(IEqualityComparer<TKey1> comparer1 = null, IEqualityComparer<TKey2> comparer2 = null)
{
_firstKeys = new Dictionary<TKey1, KeyValuePair<TKey2, TValue>>(comparer1);
_secondKeys = new Dictionary<TKey2, KeyValuePair<TKey1, TValue>>(comparer2);
}
public bool ContainsKey1(TKey1 key)
{
return ContainsKey(key, _firstKeys);
}
private static bool ContainsKey<S, T>(S key, Dictionary<S, KeyValuePair<T, TValue>> dict)
{
return dict.ContainsKey(key);
}
public bool ContainsKey2(TKey2 key)
{
return ContainsKey(key, _secondKeys);
}
public TValue GetValueByKey1(TKey1 key)
{
return GetValueByKey(key, _firstKeys);
}
private static TValue GetValueByKey<S, T>(S key, Dictionary<S, KeyValuePair<T, TValue>> dict)
{
return dict[key].Value;
}
public TValue GetValueByKey2(TKey2 key)
{
return GetValueByKey(key, _secondKeys);
}
public bool TryGetValueByKey1(TKey1 key, out TValue value)
{
return TryGetValueByKey(key, _firstKeys, out value);
}
private static bool TryGetValueByKey<S, T>(S key, Dictionary<S, KeyValuePair<T, TValue>> dict, out TValue value)
{
KeyValuePair<T, TValue> otherPairing;
bool b = TryGetValue(key, dict, out otherPairing);
value = otherPairing.Value;
return b;
}
private static bool TryGetValue<S, T>(S key, Dictionary<S, KeyValuePair<T, TValue>> dict,
out KeyValuePair<T, TValue> otherPairing)
{
return dict.TryGetValue(key, out otherPairing);
}
public bool TryGetValueByKey2(TKey2 key, out TValue value)
{
return TryGetValueByKey(key, _secondKeys, out value);
}
public bool Add(TKey1 key1, TKey2 key2, TValue value)
{
if (ContainsKey1(key1) || ContainsKey2(key2)) // very important
return false;
AddOrUpdate(key1, key2, value);
return true;
}
// dont make this public; a dangerous method used cautiously in this class
private void AddOrUpdate(TKey1 key1, TKey2 key2, TValue value)
{
_firstKeys[key1] = new KeyValuePair<TKey2, TValue>(key2, value);
_secondKeys[key2] = new KeyValuePair<TKey1, TValue>(key1, value);
}
public bool UpdateKey1(TKey1 oldKey, TKey1 newKey)
{
return UpdateKey(oldKey, _firstKeys, newKey, (key1, key2, value) => AddOrUpdate(key1, key2, value));
}
private static bool UpdateKey<S, T>(S oldKey, Dictionary<S, KeyValuePair<T, TValue>> dict, S newKey,
Action<S, T, TValue> updater)
{
KeyValuePair<T, TValue> otherPairing;
if (!TryGetValue(oldKey, dict, out otherPairing) || ContainsKey(newKey, dict))
return false;
Remove(oldKey, dict);
updater(newKey, otherPairing.Key, otherPairing.Value);
return true;
}
public bool UpdateKey2(TKey2 oldKey, TKey2 newKey)
{
return UpdateKey(oldKey, _secondKeys, newKey, (key1, key2, value) => AddOrUpdate(key2, key1, value));
}
public bool UpdateByKey1(TKey1 key, TValue value)
{
return UpdateByKey(key, _firstKeys, (key1, key2) => AddOrUpdate(key1, key2, value));
}
private static bool UpdateByKey<S, T>(S key, Dictionary<S, KeyValuePair<T, TValue>> dict, Action<S, T> updater)
{
KeyValuePair<T, TValue> otherPairing;
if (!TryGetValue(key, dict, out otherPairing))
return false;
updater(key, otherPairing.Key);
return true;
}
public bool UpdateByKey2(TKey2 key, TValue value)
{
return UpdateByKey(key, _secondKeys, (key1, key2) => AddOrUpdate(key2, key1, value));
}
public bool RemoveByKey1(TKey1 key)
{
return RemoveByKey(key, _firstKeys, _secondKeys);
}
private static bool RemoveByKey<S, T>(S key, Dictionary<S, KeyValuePair<T, TValue>> keyDict,
Dictionary<T, KeyValuePair<S, TValue>> valueDict)
{
KeyValuePair<T, TValue> otherPairing;
if (!TryGetValue(key, keyDict, out otherPairing))
return false;
if (!Remove(key, keyDict) || !Remove(otherPairing.Key, valueDict))
throw new Exception("somewhere logic went wrong and your data got corrupt");
return true;
}
private static bool Remove<S, T>(S key, Dictionary<S, KeyValuePair<T, TValue>> dict)
{
return dict.Remove(key);
}
public bool RemoveByKey2(TKey2 key)
{
return RemoveByKey(key, _secondKeys, _firstKeys);
}
public void Clear()
{
_firstKeys.Clear();
_secondKeys.Clear();
}
public IEnumerator<KeyValuePair<Tuple<TKey1, TKey2>, TValue>> GetEnumerator()
{
if (_firstKeys.Count != _secondKeys.Count)
throw new Exception("somewhere logic went wrong and your data got corrupt");
return _firstKeys.Select(kvp => new KeyValuePair<Tuple<TKey1, TKey2>, TValue>(Tuple.Create(kvp.Key, kvp.Value.Key),
kvp.Value.Value)).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Dictionary<Guid, Object> objs = new Dictionary<Guid, Object>();
Dictionary<int, Guid> guids = new Dictionary<int, Guid>();
private void Set(object sender, Object obj)
{
objs[obj.Guid] = obj;
guids[obj.Id] = obj.Guid;
}
public Object Get(int id)
{
return guids.ContainsKey(id) ? Get(guids[id]) : null;
}
public Object Get(Guid guid)
{
return objs.ContainsKey(guid) ? objs[guid] : null;
}