2013-08-05 1 views
1

По сути, мне нужна структура данных, которая напоминает словарь, но имеет разницу в том, что ее значения также уникальны. Другими словами, в нем изображено отношение «один к одному», а не одно.Как я могу реализовать словарь, значение которого также является ключом?

Пример должен объяснить лучше. Предположим, что я называю эту новую структуру данных 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 
+1

Обратите внимание, что в данном конкретном образце может быть лучше иметь 'Dictionary <строка, пара>' и сопоставить оба имени к тому же «Пара», когда вы добавляете один ... –

+0

+1 к ответу Алексея, но, тем не менее, в мире более 1 «Джо», поэтому вам может понадобиться что-то вроде словаря <строка, список > ' – lukegravitt

+0

Просто используйте два словаря. –

ответ

1

то, что вы ищете также называется Two-way dictionary. Посмотрите на otherSOanswers на тот же вопрос.

+0

После прочтения ответа я понял, что это немного другое. Структура данных, которую он написал, позволяет myMapping.Add («Joe», «Ann»); myMapping.Add («Ann», «Joe»); // не разрешено Но я могу начать с этого момента. Благодаря! – Jimbo

0

Два словаря не нужны - достаточно словаря с HashSet. Разумеется, HashSet будет удерживать и защищать значения.

EDIT: дополнительное пояснение касательно вопроса в комментарии

Новая коллекция будет состоять из экземпляра словаря и 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); 
} 
+0

Этот хэш будет для каждого значения или для всех значений? Я имею в виду, вы проверите значение в этом хэш-наборе перед вставкой записи в словарь? – AKS

1

Я начал строить TwoWayDictionary для вас на основе IDictionary 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 
Смежные вопросы