lunes, 22 de abril de 2013

Dictionary con dos keys

Hace un tiempo, mientras desarrollaba mi antiguo servidor privado para un juego, llego un momento en que se convirtio en una idea bastante util pensar en una manera de tener un valor a asociado a 2 llaves distintas.
el problema fue el siguiente.

Por motivos de como estaba estructurados los paquetes de datos, cada persona conectada, tenia una ID, y obviamente, un personaje asociado, pero... que pasaba cuando necesitaba a alguien con determinado nombre? necesitaba comparar los nombres en un ciclo.

Esta clase la llame "selector", son 3 dictionary thread-safe dispuestos de la siguiente manera
<llave1, valor>
<llave1, llave2>
<llave2, llave1>

dos consultas en un caso suena mejor que sobre 50 comparaciones de strings, o no? :)

Los metodos de obtencion y actualizacion que implemente son los "seguros" por asi decirlo
TryGet....(...., out ....); 

y la obtencion de un ICollection para poder aplicar ciclos al selector :)


    public class Selector<TKey1, TKey2, TValue>
    {
        ConcurrentDictionary<TKey1, TValue> Key1ToValue;
        ConcurrentDictionary<TKey2, TKey1> Key2ToKey1;
        ConcurrentDictionary<TKey1, TKey2> Key1ToKey2;

        public Selector()
        {
            Key1ToValue = new ConcurrentDictionary<TKey1, TValue>();
            Key2ToKey1 = new ConcurrentDictionary<TKey2, TKey1>();
            Key1ToKey2 = new ConcurrentDictionary<TKey1, TKey2>();
        }

        public bool TryGetValue(TKey1 key, out TValue value)
        {
            return Key1ToValue.TryGetValue(key, out value);
        }

        public bool TryGetValue(TKey2 key2, out TValue value)
        {
            TKey1 key1;
            if (Key2ToKey1.TryGetValue(key2, out key1))
                return Key1ToValue.TryGetValue(key1, out value);
            value = default(TValue);
            return false;
        }

        public bool TryGetKey1(TKey2 key2, out TKey1 value)
        {
            return Key2ToKey1.TryGetValue(key2, out value);
        }

        public bool TryGetKey2(TKey1 key1, out TKey2 value)
        {
            return Key1ToKey2.TryGetValue(key1, out value);
        }

        public bool TryAdd(TKey1 key1, TKey2 key2, TValue value)
        {
            return (Key1ToKey2.TryAdd(key1, key2) &&
                    Key1ToValue.TryAdd(key1, value) &&
                    Key2ToKey1.TryAdd(key2, key1));
        }

        public bool TryRemove(TKey1 key1)
        {
            TValue deletedval;
            TKey1 deleted1;
            TKey2 key2;

            if (Key1ToKey2.TryRemove(key1, out key2))
                return (Key2ToKey1.TryRemove(key2, out deleted1) &&
                       Key1ToValue.TryRemove(key1, out deletedval));
            return false;



        }

        public bool ContainsKey1(TKey1 value)
        {
            return Key1ToValue.ContainsKey(value);
        }

        public bool ContainsKey2(TKey2 value)
        {
            return Key2ToKey1.ContainsKey(value);
        }

        public bool ContainsValue(TValue value)
        {
            return Key1ToValue.Values.Contains(value);
        }

        public ICollection<TKey1> Keys1
        {
            get { return Key1ToKey2.Keys; }
        }

        public ICollection<TKey2> Keys2
        {
            get { return Key2ToKey1.Keys; }
        }

        public ICollection<TValue> Values
        {
            get { return Key1ToValue.Values; }
        }
    }

Como se imaginaran, por ser thread-safe y ser 3 dictionaies, la obtencion de un valor por medio de la llave 1   se ve un poco mas lento, aun asi, satisface las necesidades de cualquier situacion. en casos de necesitarse mas velocidad que thread-safe obviamente es recomendable cambiarlos a Dictionary, concurrentDictionary puede llegar a ser 5 veces mas lento en la obtencion de datos

1 comentario:

  1. Are you a gambler? Casino Sites - ONE Casino Review
    Casino Sites - 피망 포커 머니 상 If you enjoy playing online poker, then you probably 포커 게임 know 마틴 게일 전략 there is something for 강원 랜드 칩 걸썰 everyone in the gambling 저녁밥 추천 world: a lack of quality.

    ResponderEliminar