1

本质上,我想要一个类似于 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
4

3 回答 3

1

您要查找的内容也称为Two-way dictionary. 看看对同一问题的其他 SO 答案。

于 2013-08-05T21:33:43.920 回答
1

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

//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
于 2013-08-06T01:41:57.317 回答
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);
}
于 2013-08-05T22:04:55.140 回答