Багатозначний словник


76

Як створити багатозначний словник на c #?

Наприклад, Dictionary<T,T,T>де перший T - ключ, а інші два - значення.

так це було б можливо: Dictionary<int,object,double>

Дякую

Відповіді:


62

Просто створіть Pair<TFirst, TSecond>тип і використовуйте його як своє значення.

У мене є приклад одного в моєму C # у вихідному коді Depth . Тут відтворено для простоти:

using System;
using System.Collections.Generic;

public sealed class Pair<TFirst, TSecond>
    : IEquatable<Pair<TFirst, TSecond>>
{
    private readonly TFirst first;
    private readonly TSecond second;

    public Pair(TFirst first, TSecond second)
    {
        this.first = first;
        this.second = second;
    }

    public TFirst First
    {
        get { return first; }
    }

    public TSecond Second
    {
        get { return second; }
    }

    public bool Equals(Pair<TFirst, TSecond> other)
    {
        if (other == null)
        {
            return false;
        }
        return EqualityComparer<TFirst>.Default.Equals(this.First, other.First) &&
               EqualityComparer<TSecond>.Default.Equals(this.Second, other.Second);
    }

    public override bool Equals(object o)
    {
        return Equals(o as Pair<TFirst, TSecond>);
    }

    public override int GetHashCode()
    {
        return EqualityComparer<TFirst>.Default.GetHashCode(first) * 37 +
               EqualityComparer<TSecond>.Default.GetHashCode(second);
    }
}

2
Яка перевага перед звичайним KeyValuePair? Чи є якісь накладні витрати при використанні KeyValuePair?
— tanascius

1
В основному це різниця в акцентах - хоча KeyValuePair дійсно інкапсулює пару значень, це передбачає певний тип взаємозв'язку між ними ... цього не потрібно.
— Джон Скіт,

19
Це те саме, що Tuple в .Net 4.0?
— adam0101

2
@ adam0101: Так само, так.
— Джон Скіт,

4
@BasselAlkhateeb: Якщо вам не подобається можливість повертати значення, тоді так, це добре ...
— Джон Скіт,

64

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

public struct MyValue
{
    public object Value1;
    public double Value2;
}

тоді ви могли б отримати свій словник

var dict = new Dictionary<int, MyValue>();

Ви можете навіть піти на крок далі і впровадити власний клас словника, який буде обробляти будь-які спеціальні операції, які вам знадобляться. наприклад, якщо ви хочете мати метод Add, який приймає int, object та double

public class MyDictionary : Dictionary<int, MyValue>
{
    public void Add(int key, object value1, double value2)
    {
        MyValue val;
        val.Value1 = value1;
        val.Value2 = value2;
        this.Add(key, val);
    }
}

тоді ви можете просто створити екземпляр та додати до словника таким чином, і вам не доведеться турбуватися про створення структур "MyValue":

var dict = new MyDictionary();
dict.Add(1, new Object(), 2.22);

30
Dictionary<T1, Tuple<T2, T3>>

Редагувати: Вибачте - я забув, що ви не отримуєте Tuples, поки не вийде .NET 4.0. Ой!


1
Кортежі знаходяться в .NET 4.0 BCL, і це не пов'язано з C # 4.0. Функції C # 4.0 не згадують про підтримку кортежу. Будь ласка, виправте свою відповідь.
— Eriawan Kusumawardhono

Проблема кортежу полягає в тому, що значення не називаються.
— ProfK

2
Крім того, значення кортежу читаються лише для читання, що може бути нормальним для деяких випадків, але їх слід враховувати перед їх використанням.
— Себастьян Верк

Дуже хороша інформація. Дозволив мені розширити існуючий словниковий код. Дякую.
— Mike Malter

6

Я думаю, що це цілком надмірно для семантики словника, оскільки словник за визначенням - це сукупність ключів та відповідних значень, як і те, як ми бачимо книгу словника мови, яка містить слово як ключ та його описове значення як значення.

Але ви можете представити словник, який може містити набір значень, наприклад:

Dictionary<String,List<Customer>>

Або словник ключа та значення як словник:

Dictionary<Customer,Dictionary<Order,OrderDetail>>

Тоді у вас буде словник, який може мати кілька значень.


1
Як тільки ви починаєте вкладати словники, ваш код починає виглядати як багатовимірні масиви.
— IAbstract

@IAbstract це не так схоже в семантиці. Багатовимірні масиви не дбають про комбінацію ключів-значень. Також багатовимірні масиви не дбають про максимум двох елементів (як словник повинен мати).
— Eriawan Kusumawardhono

@eriawan: Я не думаю, що мені було зрозуміло :) ... припустимо значення int для ключів: myColl[0][1]... виглядає як багатовимірний масив. Коли ви починаєте вкладати колекції, я вважаю, що пора належним чином інкапсулювати колекцію 'value'.
— IA Abstract

@IAbstract це хороший момент! Тепер я розумію вашу думку у вашому останньому коментарі. Я згоден, що нам слід правильно інкапсулювати колекцію значень.
— Eriawan Kusumawardhono

5

Я не думаю, що ви можете зробити це безпосередньо. Можна було б створити клас , який містить як ваш objectі doubleі покласти його екземпляр в словнику , хоча.

class Pair
{
    object obj;
    double dbl;
}

Dictionary<int, Pair> = new Dictionary<int, Pair>();

2

Якщо значення пов’язані, чому б не інкапсулювати їх у клас і просто використовувати звичайний старий словник?


Також буде читабельнішим, ніж Pair і Tuple. Що таке перший, другий, пункт1, пункт2?
— KornMuffin

1

Ви описуєте мультимапу.

Ви можете зробити значення об'єктом List, щоб зберегти більше одного значення (> 2 для розширюваності).

Замінити об’єкт словника.


1

Я вирішив за допомогою:

Dictionary<short, string[]>

Подобається це

Dictionary<short, string[]> result = new Dictionary<short, string[]>();
result.Add(1,
           new string[] 
                    { 
                    "FirstString",
                    "Second"
                    }
                );
        }
return result;

1

Я знаю, що це стара тема, але - оскільки про це не згадували, це працює

  Dictionary<string, object> LookUp = new Dictionary<string, object>();
  LookUp.Add("bob", new { age = "23", height = "2.1m", weight = "110kg"});
  LookUp.Add("jasper", new { age = "33", height = "1.75m", weight = "90kg"});
  foreach(KeyValuePair<string, object> entry in LookUp )
  {
      object person = entry.Value;
      Console.WriteLine("Person name:" + entry.Key + " Age: "  + person.age);          
  }

0

Ось реалізація одного ключа для багатозначної карти в C #, який використовує набір типів ключів:

https://github.com/ColmBhandal/CsharpExtras/blob/master/CsharpExtras/Dictionary/MultiValueMapImpl.cs

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

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