【问题标题】:How can I implement a dictionary whose value is also a key?如何实现一个值也是键的字典?
【发布时间】:2013-08-06 17:54:12
【问题描述】:

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

【问题讨论】:

  • 请注意,在此特定示例中,添加 Dictionary&lt;string, Couple&gt; 并将两个名称映射到同一个 Couple 对象可能会更好...
  • +1 对阿列克谢的回答,但即便如此,世界上还有不止 1 个“乔”,所以你可能想要Dictionary&lt;string, List&lt;Couple&gt;&gt;
  • 只用两个字典。
  • 正如 Hans Passant 所说,使用两本字典。您可以将其包装成一个类,如下所示stackoverflow.com/a/255638/187697
  • @lukegravitt 但不允许第二次添加 Joe(参见 Joe, Mary 条目)。所以乔只得到一个映射。

标签: c# data-structures dictionary


【解决方案1】:

您要查找的内容也称为Two-way dictionary。看看otherSOanswers对同一个问题。

【讨论】:

  • 看完答案后,我意识到它有点不同。他编写的数据结构允许 myMapping.Add("Joe", "Ann"); myMapping.Add("Ann", "Joe");// 不允许但我可以从那里开始。谢谢!
【解决方案2】:

我开始根据 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

【讨论】:

    【解决方案3】:

    两个字典不是必需的 - 带有 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);
    }
    

    【讨论】:

    • 那个hashset是针对每个值,还是针对所有值?我的意思是你会在字典中插入记录之前验证该哈希集中的值吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-21
    • 1970-01-01
    • 1970-01-01
    • 2018-12-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多