2016-03-23 9 views
5

In einem Dictionary<struct,int>: ist es möglich, Add/Set in einem Anruf?C# Wörterbuch Add/Set in einem Anruf aus Leistungsgründen

Also ist es möglich, den folgenden Code in nur einer Suche pro Eintrag zu tun?

Dies geschieht in einer sehr engen Schleife über eine große Menge von Daten, so dass alle Leistung zählt.

Oder gibt es eine bessere geeignete Datenstruktur?

+1

Ich glaube nicht, dass Sie vermeiden können, in das Wörterbuch zweimal zu indizieren (einmal, um einen vorhandenen Wert zu erhalten, und wieder um den Wert zu setzen), aber Sie können überspringen, indem Sie den ursprünglichen Wert auf 0 setzen, da TryGetValue das für Sie erledigt, wenn der Schlüssel nicht gefunden wird. Und Sie müssen eine Überprüfung haben, falls TryGetValue false zurückgibt. – SlimsGhost

+1

Gibt es ein _actual_ Leistungsproblem relativ zum gesamten Prozess oder ist es nur _assuming_, dass es einen gibt? Dictionary-Lookups sind O (1), daher sollte der Lookup (und das Set) sehr wenig Performance-Overhead haben. –

+0

@SlimsGhost Sie müssen das Ergebnis in diesem Fall nicht prüfen - wenn der Schlüssel dann nicht existiert '_KeyToPoints [key]' würde '0 + Punkte' an dieser Schlüsselposition speichern. Der Code wäre der gleiche, unabhängig davon, ob der Schlüssel existiert oder nicht. –

Antwort

2

Ja, es gibt einen Weg, dies zu tun, aber es hat einen Nachteil. Betrachten Sie diese Klasse:

class Ref<T> 
{ 
    public T Value; 
} 

Sie ein Dictionary<K, Ref<int>> dict verwenden kann und dann dies tun:

Ref<int> count; 
if (!dict.TryGetValue(key, out count)) 
{ 
    count = new Ref<int> { Value = 0 }; 
    dict[key] = count; 
} 
count.Value += points; 

Der Nachteil, dass jetzt Sie haben ein zusätzliches Heap-Objekt pro Eintrag im Wörterbuch. Abhängig von Ihrer Situation kann dies akzeptabel sein oder auch nicht.

+0

Ist das tatsächlich schneller? Sie haben praktisch dieselben Operationen an Ort und Stelle und der allererste Treffer (beim Hinzufügen eines Elements zum Wörterbuch) ist noch schwerer, weil Sie ein Objekt erstellt haben. –

+1

@QualityCatalyst Die beiden Ansätze müssten profiliert werden. Die Frage, wie ich sie interpretierte, war einfach, ob es möglich war, dies mit nur einer Wörterbuchsuche zu tun. Ich habe gerade erklärt, dass es möglich ist und qualitativ die Nachteile charakterisiert. Es kann sein, dass Profiling zeigt, dass dies ein schrecklicher Ansatz für die Performance ist, aber ich glaube nicht, dass dies die Antwort ungültig macht. –

+0

Danke, Timothy aber das schafft in diesem Fall in der Tat viel größere Probleme :) Ich denke, ich habe meine Frage nicht gut genug angegeben. Wenn das wirklich der einzige Weg ist, werde ich es trotzdem akzeptieren –

-1

Sehr unangenehme Lösung, aber es wird schneller unter der Annahme, dass Sie die AddPoints() Methode meist für bereits vorhandene Elemente im Wörterbuch aufrufen.

Das Werfen und Behandeln von Ausnahmen ist sehr teuer (zeitaufwändig) und beeinträchtigt Ihre Leistung negativ. Um dies zu vermeiden, können Sie das Wörterbuch folgendermaßen füllen:

void PreFillKeys(params T[] keys) // use an IEnumerable<T> if handier 
{ 
    foreach (T key in keys) 
    { 
     // EITHER THIS: 
     if (!_KeyToPoints.ContainsKey(key)) 
      _KeyToPoints[key] = 0; 
     /* OR THIS (faster if you know none of keys was added before) 
     try 
     { 
      _KeyToPoints[key] = 0; 
     } 
     catch (ArgumentException) 
     { 
      // ignore >> you shouldn't have called 
     } 
     */ 
    } 
} 
0

Sie können den alten Hashtable Behälter verwenden:

Hashtable map = new Hashtable(); 
map[key] = value; 

Wenn der Schlüssel nicht funktioniert existiert, wird sie erstellt und automatisch auf der Karte hinzufügen. Aber Sie leiden unter dem Boxing/Unboxing, wenn Sie einen Schlüssel verwenden, der ein Werttyp ist ...

Verwandte Themen