Mehrwertiges Wörterbuch


76

Wie würde ich ein mehrwertiges Wörterbuch in c # erstellen?

ZB Dictionary<T,T,T>wo das erste T der Schlüssel ist und die anderen beiden Werte sind.

das wäre also möglich: Dictionary<int,object,double>

Vielen Dank

Antworten:


62

Erstellen Sie einfach einen Pair<TFirst, TSecond>Typ und verwenden Sie diesen als Ihren Wert.

Ich habe ein Beispiel für einen in meinem C # in Depth-Quellcode . Der Einfachheit halber hier wiedergegeben:

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
Was ist der Vorteil gegenüber einem normalen KeyValuePair? Gibt es einen Overhead bei der Verwendung eines KeyValuePair?
Tanascius

1
Hauptsächlich ist es ein Unterschied in der Betonung - während KeyValuePair tatsächlich ein Wertepaar kapselt, impliziert es eine bestimmte Art von Beziehung zwischen ihnen ... das ist nicht der Fall.
Jon Skeet

18
Ist dies dasselbe wie Tuple in .Net 4.0?
Adam0101

2
@ adam0101: Ähnlich, ja.
Jon Skeet

4
@ BasselAlkhateeb: Wenn Sie nicht in der Lage sind, die Werte zurückzubekommen, dann ja, das ist in Ordnung ...
Jon Skeet

64

Wenn Sie versuchen, Werte zu gruppieren, ist dies möglicherweise eine gute Gelegenheit, eine einfache Struktur oder Klasse zu erstellen und diese als Wert in einem Wörterbuch zu verwenden.

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

dann könnten Sie Ihr Wörterbuch haben

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

Sie können sogar noch einen Schritt weiter gehen und Ihre eigene Wörterbuchklasse implementieren, die alle speziellen Operationen ausführt, die Sie benötigen würden. Zum Beispiel, wenn Sie eine Add-Methode haben möchten, die ein int, ein Objekt und ein double akzeptiert

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);
    }
}

Dann könnten Sie einfach instanziieren und wie folgt zum Wörterbuch hinzufügen, und Sie müssten sich keine Gedanken über das Erstellen von 'MyValue'-Strukturen machen:

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

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

Bearbeiten: Entschuldigung - ich habe vergessen, dass Sie keine Tupel bekommen, bis .NET 4.0 herauskommt. D'oh!


1
Tupel befinden sich in .NET 4.0 BCL und sind nicht mit C # 4.0 verwandt. In C # 4.0-Funktionen wird die Tupelunterstützung nicht erwähnt. Bitte korrigieren Sie Ihre Antwort.
Eriawan Kusumawardhono

Das Problem mit dem Tupel ist, dass die Werte nicht benannt sind.
ProfK

2
Darüber hinaus sind Tupelwerte schreibgeschützt, was in einigen Fällen in Ordnung sein kann, aber vor der Verwendung berücksichtigt werden sollte.
Sebastian Werk

Sehr gute Informationen. Erlaubte mir, vorhandenen Wörterbuchcode zu erweitern. Vielen Dank.
Mike Malter

6

Ich denke, dies ist für eine Wörterbuchsemantik ziemlich übertrieben, da das Wörterbuch per Definition eine Sammlung von Schlüsseln und ihren jeweiligen Werten ist, genau wie wir ein Sprachwörterbuch sehen, das ein Wort als Schlüssel und seine beschreibende Bedeutung als das enthält Wert.

Sie können jedoch ein Wörterbuch darstellen, das eine Sammlung von Werten enthalten kann, zum Beispiel:

Dictionary<String,List<Customer>>

Oder ein Wörterbuch eines Schlüssels und den Wert als Wörterbuch:

Dictionary<Customer,Dictionary<Order,OrderDetail>>

Dann haben Sie ein Wörterbuch, das mehrere Werte haben kann.


1
Sobald Sie anfangen, Wörterbücher zu verschachteln, sieht Ihr Code wie mehrdimensionale Arrays aus.
IAbstract

@IAbstract ist es in der Semantik nicht so ähnlich. Mehrdimensionale Arrays kümmern sich nicht um die Kombination von Schlüsselwerten. Auch mehrdimensionale Arrays kümmern sich nicht um das maximale Element von zwei (genau wie das Wörterbuch haben muss).
Eriawan Kusumawardhono

@eriawan: Ich glaube nicht, dass ich klar war :) ... nehme int-Werte für Schlüssel an: myColl[0][1]... sieht aus wie ein mehrdimensionales Array. Wenn Sie mit dem Verschachteln von Sammlungen beginnen, ist es meines Erachtens an der Zeit, die 'Wert'-Sammlung entsprechend zu kapseln.
IAbstract

@IAbstract das ist ein guter Punkt! Jetzt verstehe ich Ihren Punkt in Ihrem letzten Kommentar. Ich bin damit einverstanden, dass wir die Wertsammlung richtig kapseln.
Eriawan Kusumawardhono

5

Ich glaube nicht, dass Sie das direkt tun können. Sie können jedoch eine Klasse erstellen, die sowohl Ihr objectals auch enthält, doubleund eine Instanz davon in das Wörterbuch aufnehmen.

class Pair
{
    object obj;
    double dbl;
}

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

2

Wenn die Werte zusammenhängen, können Sie sie in eine Klasse einkapseln und einfach das einfache alte Wörterbuch verwenden.


Wird auch besser lesbar sein als Pair und Tuple. Was ist First, Second, Item1, Item2?
KornMuffin

1

Sie beschreiben eine Multimap.

Sie können den Wert zu einem Listenobjekt machen, um mehr als einen Wert zu speichern (> 2 zur Erweiterbarkeit).

Überschreiben Sie das Wörterbuchobjekt.


1

Ich löste mit:

Dictionary<short, string[]>

So was

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

1

Ich weiß, dass dies ein alter Thread ist, aber - da er nicht erwähnt wurde, funktioniert dies

  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

Hier ist eine Implementierung einer einzelnen Schlüssel-zu-Mehrwert-Zuordnung in C #, die einen satzbasierten Schlüsseltyp verwendet:

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

Das Wörterbuch verhält sich wie ein reguläres Wörterbuch vom Schlüsseltyp zu einem Satz des Werttyps, bietet jedoch auch Funktionen zum direkten Hinzufügen eines einzelnen Werts des Werttyps und übernimmt im Hintergrund die Erstellung eines zugrunde liegenden Satzes und / oder das Hinzufügen zu das Set.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.