Какую структуру данных я должен использовать? - PullRequest
4 голосов
/ 22 октября 2011

У меня проблема с отображением двух входов на один выход.

Я знаю, что словарь - это типизированное линейное отображение:

для каждого x (key) может быть y (value)

Мне нужно многомерное отображение:

для каждого x, y (key) может быть z (value)

Но, конечно, главное, что мне нужно, чтобы он поддерживал универсальную типизацию и имел динамический размер.

Существует ли эта структура данных в C # или мне нужно создать словарь словарей? Я бы предпочел не изобретать велосипед, если мне не нужно.


Изобретая колесо:

using System;
using System.Collections.Generic;
using System.Text;

namespace zlib.Collections
{
    public class Dictionary3D<Tx, Ty, Tz>
    {
        private Dictionary<Tuple<Tx, Ty>, Tz> _dict = new Dictionary<Tuple<Tx, Ty>, Tz>();

        public void Add(Tx x, Ty y, Tz z)
        {
            _dict.Add(Tuple.Create<Tx, Ty>(x, y), z);
        }

        public void Clear()
        {
            _dict.Clear();
        }

        public bool ContainsKey(Tx x, Ty y)
        {
            return _dict.ContainsKey(Tuple.Create<Tx, Ty>(x, y));
        }

        public bool ContainsValue(Tz z)
        {
            return _dict.ContainsValue(z);
        }

        public Dictionary<Tuple<Tx, Ty>, Tz>.Enumerator GetEnumerator()
        {
            return _dict.GetEnumerator();
        }

        public bool Remove(Tx x, Ty y)
        {
            return _dict.Remove(Tuple.Create<Tx, Ty>(x, y));
        }

        public bool TryGetValue(Tx x, Ty y, out Tz z)
        {
            return _dict.TryGetValue(Tuple.Create<Tx, Ty>(x, y), out z);
        }

        public int Count
        {
            get { return _dict.Count; }
        }

        public Dictionary<Tuple<Tx,Ty>,Tz>.KeyCollection Keys
        {
            get
            {
                return _dict.Keys;
            }
        }

        public Dictionary<Tuple<Tx, Ty>, Tz>.ValueCollection Values
        {
            get
            {
                return _dict.Values;
            }
        }

        public Tz this[Tx x, Ty y]
        {
            get
            {
                return _dict[Tuple.Create<Tx, Ty>(x, y)];
            }
            set
            {
                _dict[Tuple.Create<Tx, Ty>(x, y)] = value;
            }
        }
    }
}

Кажется, что изобретать колесо - победа среди ответов. Это код, который я придумал до сих пор, но я чувствую, что должен быть лучший способ, например matrix или что-то в этом роде.

Ответы [ 6 ]

4 голосов
/ 22 октября 2011

а как же

   Dictionary<Tuple<T,K>,Tuple<L,J>> 

??

1 голос
/ 22 октября 2011

Как насчет этого:

class Dict3D
{
    private Dictionary<KeyValuePair<object,object>, object> innnerDict= new Dictionary<KeyValuePair<object,object>, object>();

    public object Get(object key1, object key2)
    {
        KeyValuePair<object,object> bigKey = new KeyValuePair<object, object>(key1, key2);
        if (innnerDict.ContainsKey(bigKey))
        {
            return innnerDict[bigKey];
        }
        return null;
    }

    public void Set(object key1, object key2, object somevalue)
    {
        KeyValuePair<object, object> bigKey = new KeyValuePair<object, object>(key1, key2);
        if (innnerDict.ContainsKey(bigKey))
        {
            innnerDict[bigKey] = somevalue;
        }
        else
        {
            innnerDict.Add(bigKey, somevalue);
        }
    }
}

Вы также можете сделать его универсальным, но это простая версия.

Полагаю, что ответы означают, что если вам нужно чистое решение,вам (или кому-то еще), вероятно, придется изобретать велосипед.

1 голос
/ 22 октября 2011

PolyDictionary, о котором Чак Джаздзевски писал некоторое время назад, может дать вам то, что вы хотите, если вы используете Tupleкак ключ.На самом деле, это просто обертка вокруг словаряно это делает трюк.Посмотрите его серию блогов на эту тему:

1 голос
/ 22 октября 2011

Tuple , вероятно, то, что вы хотите:

var population = new Tuple< string, int>("New York", 7891957);

или для генериков:

var population = new Tuple< S, T>("New York", 7891957);

Для Tuple ссылочный вид здесь

Более того, если вы хотите, например, пользовательский словарь словаря, вы можете сделать это следующим образом:

using DictOfDict = Dictionary< X, Dictionary< Y, Z>> ;

Для справки смотрите здесь

1 голос
/ 22 октября 2011

Если я вас правильно понял, это то, что вам нужно:

class Key<Tx, Ty>
{
    public Tx x;
    public Ty y;

    public Key(Tx x, Ty y)
    {
        this.x = x;
        this.y = y;
    }
}

Dictionary<Key<Tx, Ty>, Tz> d;

И да, как упомянуто в комментарии, вы должны реализовать HashCode и Equals в этом классе Key.

0 голосов
/ 22 октября 2011

Я думаю, вам понадобится безопасный тип гетерогенного контейнера, который поддерживается словарем.В этом случае вам придется переопределить IDictionary и иметь свой собственный impl.К сожалению, нет класса, который вы могли бы использовать, если вы не следуете другим ответам или не находите обходной путь, я думаю.

См. Джошуа Блох , в этом случае вы можете в основном хранить любой тип как ключ,однако вы также можете ограничить это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...