如何实现一个值也是关键的字典?

时间:2013-08-05 21:30:23

标签: c# data-structures dictionary

基本上,我想要一个类似于Dictionary的数据结构,但不同的是它的值也是唯一的。换句话说,它描绘了一对一的关系,而不是一对一的关系。

一个例子应该更好地解释。假设我将这个新的数据结构称为MyMapping,我想在其中保存已婚夫妇的名字:

        MyMapping<string, string> myMapping = new MyMapping<string, string>();
        myMapping.Add("Joe", "Ann");
        myMapping.Add("Ann", "Joe");// not allowed
        myMapping.Add("Joe", "Mary");// not allowed
        myMapping.Add("William", "Katie");// ok
        string partner = myMapping["Ann"];// result is Joe
        partner = myMapping["Joe"];//result is Ann

3 个答案:

答案 0 :(得分:1)

您正在寻找的内容也称为Two-way dictionary。请查看同一问题的other SO answers

答案 1 :(得分:1)

我开始根据IDictionary为你构建一个TwoWayDictionary http://msdn.microsoft.com/en-us/library/s4ys34ea.aspx

//only one generic parameter needed, as key and value have same type.
public class TwoWayDictionary<TKey> : IDictionary<TKey, TKey>
{
  private Dictionary<TKey, TKey> _primary;
  private Dictionary<TKey, TKey> _secondary;

  public TwoWayDictionary()
  {
    _primary = new Dictionary<TKey, TKey>();
    _secondary = new Dictionary<TKey, TKey>();
  }

  public int Count {get{return _primary.Count;}}
  public bool IsReadOnly {get{return _primary.IsReadOnly;}}
  public TKey this[TKey key]
  {
    get
    {
      return this.GetValue(key);
    }
    set
    {
      this.Add(key, value);
    }
  }
  public ICollection<TKey> Keys {get {return _primary.Keys;}}
  public ICollection<TKey> Values {get {return _primary.Values;}}

  private TKey GetValue(TKey key)
  {
    if (_primary.ContainsKey(key))
    {
      return _primary[key];
    }
    if (_secondary.ContainsKey(key))
    {
      return _secondary[key];
    }
    throw new KeyNotFoundException("key is not found");
  }

  public void Add(KeyValuePair<TKey, TKey> item)
  {
    this.Add(item.Key, item.Value);
  }

  public void Add(TKey key, TKey value)
  {
    if (key == null || value == null)
    {
      throw new ArguementNullException("key or value is null");
    }
    if (_primary.ContainsKey(key) || _secondary.ContainsKey(key)
      || _primary.ContainsKey(value) || _secondary.ContainsKey(value))
    {
      throw new ArgumentException("Item with same key or value already exists");
    }
    _primary.Add(key, value);
    _secondary.Add(value, key);
  }

  public void Clear()
  {
    _primary.Clear();
    _secondary.Clear();
  }

  public void Contains(KeyValuePair<TKey, TKey> item)
  {
    return _primary.Contains(item) || _secondary.Contains(item);
  }

  public void ContainsKey(TKey key)
  {
    return _primary.ContainsKey(key) || _secondary.ContainsKey(key);
  }

  public void CopyTo(KeyValuePair<TKey, TKey>[] array, int arrayIndex)
  {
    return _primary.CopyTo(array, arrayIndex);
  }

... TODO finish implementing IDictionary

答案 2 :(得分:0)

不需要两个字典 - 带HashSet的字典就足够了。 HashSet当然会保留并保护这些值。

编辑:评论中有关问题的其他解释

新集合将包含Dictionary和HashSet的实例,如下所示:

class UniqueValueDictionary<TKey, TValue>
{
//...
private Dictionary<TKey, TValue> dictionary;
private HashSet<TValue> valueSet;
}

插入字典时,验证该值是否已存在:

public void Add(TKey key, TValue value)
{
if (valueSet.Contains(value))
{
//throw appropriate exception
}

dictionary.Add(key, value);
valueSet.Add(value);
}

删除时:

public void Remove(TKey key)
{
//check if key exists, throw exception if not
var value = dictionary[key];
dictionary.Remove(key);
valueSet.Remove(value);
}