mmofacts.com

C# Dictionary Problem

gepostet vor 18 Jahre von Fornax
Moin,
Ich habe dank diesem Post erfahren, dass es in C#/.Net Dictionarys gibt. Das habe ich dann auch gleich umgesetzt, ich finde die Dinger einfach klasse
Genug der Schwärmerei, mein aktuelles Problem ist, dass ich irgendwie keine Dictionarys in Dictionarys machen kann:
Dictionary allePlaneten = new Dictionary();

allePlaneten[1] = new Dictionary(); // Galaxie 1
allePlaneten[1][1] = new Dictionary(); // System 1
allePlaneten[1][1][1] = 0; // Planet 1; userID
EDIT:
Ach, die Fehlermeldung interesiert euch bestimmt auch:
FGEngine.cs(67,20): error CS0305: Using the generic type

'System.Collections.Generic.Dictionary' requires '2' type
arguments
c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll: (Location of symbol
related to previous error)
FGEngine.cs(67,67): error CS0305: Using the generic type
'System.Collections.Generic.Dictionary' requires '2' type
arguments
c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll: (Location of symbol
related to previous error)
FGEngine.cs(68,42): error CS0305: Using the generic type
'System.Collections.Generic.Dictionary' requires '2' type
arguments
c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll: (Location of symbol
related to previous error)
FGEngine.cs(69,4): error CS0021: Cannot apply indexing with [] to an expression
of type 'Dictionary'
FGEngine.cs(70,4): error CS0021: Cannot apply indexing with [] to an expression
of type 'Dictionary'
1 Datei(en) kopiert. (Zeile 67 entspricht hier Zeile 1)
EDIT2:
Ok, ich denke ich hab's gelöst, das ist ja ganzschön umständlich ^^

Dictionary>> allePlaneten = new Dictionary>>();
allePlaneten[1] = new Dictionary>(); // Galaxie 1
allePlaneten[1][1] = new Dictionary(); // System 1
allePlaneten[1][1][1] = 0; // Planet 1; userID
gepostet vor 18 Jahre von TheUndeadable
Nimm lieber folgendes Verfahren, damit sparst du einiges an Speicherplatz und erhältst schnellere Zugriffszeiten.

public class Triple
{
public int A;
public int B;
public int C;
public Triple(int a, int b, int c)
{
A = a;
B = b;
C = c;
}
public override bool Equals(object obj)
{
Triple t = obj as Triple;
if (t == null)
{
return false;
}
return t.A == A && t.B == B && t.C == C;
}
public override int GetHashCode()
{
return A.GetHashCode() ^ B.GetHashCode() ^ C.GetHashCode();
}
}
public class App
{
public static void Main(String[] astrArguments)
{
Dictionary aDictionary = new Dictionary();
aDictionary[new Triple(1, 1, 1)] = 12;
aDictionary[new Triple(2, 3, 4)] = 12;
Console.WriteLine(aDictionary[new Triple(2, 3, 5)]);
}
}
gepostet vor 18 Jahre von Fornax
Hab ich nur das Gefühl, oder ist es so, dass das Programm schneller läuft?
Dankeschön, sieht zwar auf den ersten Blick merkwürdig aus, aber es ist wirklich würdig zu merken. Immer diese Wortspiele ^^
Jetzt habe ich nurnoch ein kleines (performance) Problemchen. Kann ich von Anfang an sagen, dass der Standartwert 0 ist? Jetzt laufe ich noch per Schleife alles durch und setze es auf 0. Das ist suboptimal
gepostet vor 18 Jahre von TheUndeadable
Du darfst das Dictionary nicht mit dem assoziativen Array von PHP verwechseln.
Aber auch da kann dir C# natürlich helfen:

using System;
using System.Collections.Generic;
public class Triple
{
public int A;
public int B;
public int C;
public Triple(int a, int b, int c)
{
A = a;
B = b;
C = c;
}
public override bool Equals(object obj)
{
Triple t = obj as Triple;
if (t == null)
{
return false;
}
return t.A == A && t.B == B && t.C == C;
}
public override int GetHashCode()
{
return A.GetHashCode() ^ B.GetHashCode() ^ C.GetHashCode();
}
}
public class TripleDictionary
{
Dictionary _Dictionary;
public TripleDictionary()
{
_Dictionary = new Dictionary();
}
public int this[int A, int B, int C]
{
get
{
int nReturn;
if (_Dictionary.TryGetValue(new Triple(A, B, C), out nReturn))
{
return nReturn;
}
return 0;
}
set
{
_Dictionary[new Triple(A, B, C)] = value;
}
}
}
public class App
{
public static void Main(String[] astrArguments)
{
TripleDictionary oDictionary = new TripleDictionary();
oDictionary[2, 3, 5] = 432;
oDictionary[2, 5, 7] = 4593;
Console.WriteLine(oDictionary[2, 3, 5]);
Console.WriteLine(oDictionary[2, 3, 6]);
Console.ReadKey();
}
}
Du überlädst von deinem Zwischenobjekt einfach den Operator [] und kannst dann auf das Dictionary zugreifen.
Wenn du andere Funktionen vom Dictionary brauchst, musst du sie Durchleiten:

public void Clear() { _Dictionary.Clear(); }
etc....
> Hab ich nur das Gefühl, oder ist es so, dass das Programm schneller läuft?
Wahrscheinlich läuft das Programm mit den Triples schneller, da man sich nicht durch drei Dictionaries durchschlagen muss. Durch die Hashingfunktion wird sehr schnell der richtige 'Korb' gefunden, in dem dein gesuchtes Objekt liegt. Dann muss man nur noch diesen Korb durchgehen und auf Gleichheit prüfen. Dies sind 3 Int32-Vergleiche, die parallelisierbar sind und vom JustInTime-Compiler auf die unterschiedlichen Pipelines deines Prozessors verteilt werden.
gepostet vor 18 Jahre von Fornax
Ich hab das jetzt mal umgesetzt, einen spürbaren Performaceunterschied habe ich nicht festgestellt, aber das ist dann wohl der bessere Weg.
Irgendwie sind bei mir auf der Karte viele, jedoch nicht alle, Planeten unbewohnt (userID = 0), aber das ist denk ich ein Problem meinerseits *such* Bestimmt irgendwas von PHP, also der Kartengenerierung...
Was mir grad auffällt: Der Hash von (1|1|22) ist der gleiche wie von (1|2|21), ebenso (1|1|23) wie (1|2|20). (Ich denke das ist bei allen Feldern so...) Macht das Probleme, oder ist das normal?
> Du darfst das Dictionary nicht mit dem assoziativen Array von PHP verwechseln.
Ich glaube, das habe ich anfangs
gepostet vor 18 Jahre von TheUndeadable
> Was mir grad auffällt: Der Hash von (1|1|22) ist der gleiche wie von (1|2|21), ebenso (1|1|23) wie (1|2|20). (Ich denke das ist bei allen Feldern so...) Macht das Probleme, oder ist das normal?
Das ist OK, wenn auch nicht optimal, wenn du zuviel Kollissionen hast. Wenn zwei Objekte den gleichen Hash haben, heißt dies, dass sie im gleichen Korb landen. Damit kannst du bei zuvielen Kollisionen eine ungleichmäßige Verteilung deiner Objekte haben.
Um optimaler zu arbeiten kannst du ja folgendes als Hashfunktion nehmen:
return (A * 1000000) ^ (B* 1000) ^ C;
gepostet vor 18 Jahre von Fornax
Ok, das bedenke ich heute Abend in der SBahn mit Zettel und Stift

Auf diese Diskussion antworten