135 votes

Dictionnaire bidirectionnel / bidirectionnel en C #?

Je veux stocker les mots dictionnaire de la manière suivante:

Je peux obtenir le mot de code par le mot: dict["SomeWord"] -> 123 et obtenir mot par mot code: dict[123] -> "SomeWord"

Est-il vrai? Bien sûr, une façon de le faire est de deux dictionnaires: Dictionary<string,int> et Dictionary<int,string> mais est-il une autre voie?

139voto

Enigmativity Points 26345

J'ai envoyé un petit couple de classes qui permet de faire ce que vous voulez. Vous auriez probablement besoin de l'étendre avec plus de fonctionnalités, mais c'est un bon point de départ.

L'utilisation du code ressemble à ceci:

var map = new Map<int, string>();

map.Add(42, "Hello");

Console.WriteLine(map.Forward[42]);
// Outputs "Hello"

Console.WriteLine(map.Reverse["Hello"]);
//Outputs 42

Voici la définition:

public class Map<T1, T2>
{
    private Dictionary<T1, T2> _forward = new Dictionary<T1, T2>();
    private Dictionary<T2, T1> _reverse = new Dictionary<T2, T1>();

    public Map()
    {
        this.Forward = new Indexer<T1, T2>(_forward);
        this.Reverse = new Indexer<T2, T1>(_reverse);
    }

    public class Indexer<T3, T4>
    {
        private Dictionary<T3, T4> _dictionary;
        public Indexer(Dictionary<T3, T4> dictionary)
        {
            _dictionary = dictionary;
        }
        public T4 this[T3 index]
        {
            get { return _dictionary[index]; }
            set { _dictionary[index] = value; }
        }
    }

    public void Add(T1 t1, T2 t2)
    {
        _forward.Add(t1, t2);
        _reverse.Add(t2, t1);
    }

    public Indexer<T1, T2> Forward { get; private set; }
    public Indexer<T2, T1> Reverse { get; private set; }
}

10voto

zmbq Points 18714

Vous pouvez utiliser deux dictionnaires, comme vous l'avez dit, ou si les deux clés et les valeurs sont du même type, vous pouvez simplement utiliser l'une:

dict["SomeWord"]= "123" et dict["123"]="SomeWord" l'utiliser pour toutes les recherches.

6voto

HackedByChinese Points 18294

Vous pouvez utiliser cette méthode d'extension, même si elle utilise de l'énumération, et donc peut-être pas aussi performant pour les grands ensembles de données. Si vous êtes inquiet au sujet de l'efficacité, alors vous avez besoin de deux dictionnaires. Si vous voulez enchaîner les deux dictionnaires dans une classe, voir la accepté de répondre à cette question: Bidirectionnel 1 à 1 Dictionnaire en C#

public static class IDictionaryExtensions
{
    public static TKey FindKeyByValue<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TValue value)
    {
        if (dictionary == null)
            throw new ArgumentNullException("dictionary");

        foreach (KeyValuePair<TKey, TValue> pair in dictionary)
            if (value.Equals(pair.Value)) return pair.Key;

        throw new Exception("the value is not found in the dictionary");
    }
}

0voto

Blam Points 17325

Il utilise un indexeur pour la recherche inversée.
La recherche inversée est O(n) mais également de ne pas utiliser deux dictionnaires

public sealed class DictionaryDoubleKeyed : Dictionary<UInt32, string>
{   // used UInt32 as the key as it has a perfect hash
    // if most of the lookup is by word then swap
    public void Add(UInt16 ID, string Word)
    {
        if (this.ContainsValue(Word)) throw new ArgumentException();
        base.Add(ID, Word);
    }
    public UInt32 this[string Word]
    {   // this wil be O(n)
        get
        {
            return this.FirstOrDefault(x => x.Value == Word).Key;
        }
    } 
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X