Найкраще втілення для структури даних даних ключових значень?


74

Отож я останнім часом трохи потикався з C #, і всі Загальні колекції мене трохи бентежать. Скажімо, я хотів представити структуру даних, де головою дерева була пара значень ключа, а потім є один необов’язковий список пар значень ключа нижче цього (але не більше рівнів, ніж ці). Чи підходить це?

public class TokenTree
{
    public TokenTree()
    {
        /* I must admit to not fully understanding this,
         * I got it from msdn. As far as I can tell, IDictionary is an
         * interface, and Dictionary is the default implementation of
         * that interface, right?
         */
        SubPairs = new Dictionary<string, string>();
    }

    public string Key;
    public string Value;
    public IDictionary<string, string> SubPairs;
}

Насправді це просто простий шунт для передачі даних.

Відповіді:


137

Існує фактичний Тип даних, який називається KeyValuePair, використовуйте так

KeyValuePair<string, string> myKeyValuePair = new KeyValuePair<string,string>("defaultkey", "defaultvalue");

1
Це чудово працює з оператором "using" (подібним до старого typedef), щоб заощадити набір тексту та зробити все зрозумілішим. Якщо ви постійно використовуєте, наприклад, пару (string, string).
Andreas Reiff,

8
KeyValuePair <рядок, рядок> NAME_HERE = новий KeyValuePair <рядок, рядок> ("ключ за замовчуванням", "значення за замовчуванням");
HasanAboShally

1
Щоб розширити коментар @AndreasReiff: using NameValuePair = System.Collections.Generic.KeyValuePair<string, string>;вгорі кожного файлу, який потребує (string, string)структури. Хоча мені було зручніше створити class NameValuePairв моєму просторі імен: public class NameValuePair { KeyValuePair<string, string> it; public NameValuePair( string name, string value ) { it = new KeyValuePair<string, string>( name, value ); } public string Name { get { return it.Key; } } public string Value { get { return it.Value; } } }
ToolmakerSteve

12

Однією з можливих речей, яку ви можете зробити, є використовувати об’єкт «Словник» прямо з коробки, а потім просто розширити його за допомогою власних модифікацій:

public class TokenTree : Dictionary<string, string>
{
    public IDictionary<string, string> SubPairs;
}

Це дає вам перевагу в тому, що вам не потрібно застосовувати правила IDictionary для вашого ключа (наприклад, унікальність ключа тощо).

Ага, ви правильно зрозуміли концепцію конструктора :)


7

Я думаю, що після того, як ви можете піти (як буквальне втілення вашого питання), це:

public class TokenTree
{
    public TokenTree()
    {
        tree = new Dictionary<string, IDictionary<string,string>>();
    }

    IDictionary<string, IDictionary<string, string>> tree; 
}

Ви насправді сказали "список" ключів і значень у своєму запитанні, тому, можливо, ви захочете поміняти внутрішнє IDictionaryна:

IList<KeyValuePair<string, string>>

5

Існує вбудований тип KeyValuePair. Власне кажучи, це те, до чого IDictionary дає вам доступ, коли ви в ньому переглядаєте.

Крім того, ця структура навряд чи є деревом, пошук більш репрезентативної назви може бути гарною вправою.


3

До цього слід додати лише одне (хоча, я думаю, ви вже відповіли на ваше запитання іншими). В інтересах розширюваності (оскільки всі ми знаємо, що це відбудеться в якийсь момент), можливо, ви захочете перевірити Складений шаблон. Це ідеально підходить для роботи з "деревоподібними структурами" ..

Як я вже сказав, я знаю, що ви очікуєте лише одного підрівню, але це дійсно може бути для вас корисним, якщо згодом вам потрібно буде продовжити ^ _ ^


2

@ Jay Mooney : Загальний клас словника в .NET насправді є хеш-таблицею, лише із фіксованими типами.

Код, який ви показали, не повинен переконувати когось використовувати Hashtable замість Словника, оскільки обидва фрагменти коду можуть використовуватися для обох типів.

Для хеш-таблиці:

foreach(object key in h.keys)
{
     string keyAsString = key.ToString(); // btw, this is unnecessary
     string valAsString = h[key].ToString();

     System.Diagnostics.Debug.WriteLine(keyAsString + " " + valAsString);
}

Для словника:

foreach(string key in d.keys)
{
     string valAsString = d[key].ToString();

     System.Diagnostics.Debug.WriteLine(key + " " + valAsString);
}

І те саме саме для іншого з KeyValuePair, просто використовуйте не загальну версію для Hashtable, а загальну версію для Dictionary.

Отже, це так само просто в обидві сторони, але Hashtable використовує Object як для ключа, так і для значення, а це означає, що ви встановите всі типи значень, і у вас немає безпеки типу, а Dictionary використовує загальні типи і, отже, кращий.



1

Використовуйте щось подібне:

class Tree < T > : Dictionary < T, IList< Tree < T > > >  
{  
}  

Це негарно, але я думаю, що це дасть вам те, що ви хочете. Шкода, що KeyValuePair опечатаний.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.