Welchen Array-Typ bei einem Schlüssel und mehreren Werten verwenden?

flotschie

Mitglied
Hi,

also mein Problem ist folgendes: Ich habe ca. 40.000 Schlüssel/Werte die ich in einer Liste anlegen muss. Das Problem ist das zu jedem Schlüssel 5 Werte gehören. Das heisst, Hashtable fällt weg - der kann schließlich nur pro Schlüssel einen Wert speichern.

Die Liste muss zudem noch auch irrsinnig schnell sein. Ich bekomme pro halbe Sekunde für ungef. 50 - 1000 Schlüssel Events. In diesen Events müssen die Werte der Schlüssel upgedated und verglichen werden. Das heisst also das das "Springen" zu den einzelnen Schlüsseln sehr schnell gehen muss.

Die Schlüsseln sind siebenstellige Zahlenwerte. Ich habe vorerst das Problem so gelöst, das ich einmal einen Array mit Grösse 10.000.000 angelegt habe. Danach habe ich die Schlüssel als Array-Indexe "Verpackt", also so:

Code:
Dim arr(10000000,4) as single
...
'Schlüssel ist 1234567:
arr(1234567,0) = 23 
arr(1234567,1) = 55 
arr(1234567,2) = 3 
arr(1234567,3) = 2 
arr(1234567,4) = 98

...und so weiter bis alle 40.000 Schlüssel angelegt sind. Leider sind die Schlüssel nicht fortlaufend nummeriert, sondern halt unregelmässig. Also auf 1234567 folgt dann 1238888, dann 1260000 etc....

Sobald dann der Array befüllt ist, "prasseln" die Events ein. Meine Methode funktioniert eigentlich nicht schlecht, da im Event der Schlüssel mitgeliefert wird und der index sofort mit dem Schlüssel angesprochen werden kann. Trotzdem kommt sie mir etwas unorthodox vor, da eigentlich ein Array der Grösse 10 Millionen mit nur 40.000 Einträgen befüllt wird. Gibts da bessere Methoden?
 
Wie wäre es wenn du eine eigene typsichere Auflistung erstellst?
anbieten würde sich erstmal eine Klasse/Struktur für die Schlüssel/Wertepaare. 5 oder 6 Properties für Schlüssel und Werte.

Dann leitest du eine Klasse von dictionaryBase (eigentlich ist es eine Hashtable, warum es nicht HashtableBase genannt wurde ist mir schleierhaft) ab und überschreibst du benötigten (Add, Remove, etc) Methoden, die dann dein Objekt als Parameter erwarten.

Ich würd dir das zwar gerne an einem Codebeispiel zeigen, in VB.NET würde mir das allerdings zu lange dauern, da ich normalerweise nur C# programmiere. Such einfach mal nach 'typsicherer Auflistung' oder 'typsafe collection' bei Google :)
 
danke für den tipp, werd allerdings nicht 100% schlau aus deiner Vorgehensweise: Was meinst du damit, ZUERST eine eigene typensichere Auflistung erstellen, DANN eine bestehende Klasse hernehmen (wo ich gar net weiss ob das in VB.NET geht...).

Wenn du geschrieben hättest: "Nimm doch eine bestehende Auflistungsklasse her wie den Hashtable und mach eine neue draus" hätt ichs komplett verstanden -hast du es auch so gemeint?
 
Fast :)
Ich meinte es so. Du erstellst dir eine Klasse mit 5 Properties (da es ja 5 Werte sind die du speichern musst) und wenn du willst noch mit einem Feld für den Schlüssel.
Anstatt der Hashtable nun zu jedem Key nur einen Wert zu übergeben, übergibst du ihr für jeden Key eine Instanz deiner Klasse die die benötigten Werte enthält.

Dies könntest du auch mit einer normalen Hashtable machen, allerdings nimmst sie nur Objekte vom Typ 'object' (sozusagen die Basisklasse von allem im .NET Framework) an. Das heißt du müsstest jedesmal wenn du ein Objekt aus der Hashtable zurückholst es wieder in den Typ deiner Klasse casten.

Also erstellst du dir am besten eine 'eigene' Hashtable, die direkt mit deiner Klasse umgehen kann.

Wenn du willst, kann ich dir den C#-Code dafür posten. Sollte eigentlich auch für einen VB.NET-ler zu lesen sein :) Nur umgeschrieben muss es dann noch werden..

//EDIT: Grundsätzlich geht alles was mit C# geht auch mit VB.NET. Außer dem Syntax ist nahezu kein Unterschied zwischen den Sprachen (außer einige kleine Dinge die es nur in einer der beiden Sprachen gibt, zb Operatorenüberladung)
 
Deine Klasse:

Code:
public class MyClass
	{
		int key;
		int wert1;
		int wert2;
		int wert3;
		int wert4;
		int wert5;

		public int Key
		{
			get { return key; }
			set { key = value; }
		}

		public int Wert1
		{
			get { return wert1; }
			set { wert1 = value; }
		}

		public int Wert2
		{
			get { return wert2; }
			set { wert2 = value; }
		}

		public int Wert3
		{
			get { return wert3; }
			set { wert3 = value; }
		}

		public int Wert4
		{
			get { return wert4; }
			set { wert4 = value; }
		}

		public int Wert5
		{
			get { return wert5; }
			set { wert5 = value; }
		}

		public MyClass(int key, int Wert1, int Wert2, int Wert3, int Wert4, int Wert5)
		{
			this.key = key;
			this.wert1 = Wert1;
			this.wert2 = Wert2;
			this.wert3 = Wert3;
			this.wert4 = Wert4;
			this.wert5 = Wert5;
		}
		
		//Wird überschreiben weil eine Collection damit 2 Objekte vergleicht
		public override bool Equals(object obj)
		{
			MyClass c = (MyClass) obj;
			if(this.key == c.Key)
				return true;
			else
				return false;
		}

	}

Die Hashtable:

Code:
public class MyHashtable : System.Collections.DictionaryBase
	{

		public MyClass Add(MyClass c)
		{
			Dictionary.Add(c.Key,c);
			return c;
		}

		public bool Contains(int key)
		{
			return Dictionary.Contains(key);
		}

		public void Remove(int id)
		{
			Dictionary.Remove(id);
		}
		
		//Indizier für den Zugriff über einen Index
		public MyClass this[int id]
		{
			set{ Dictionary[id] = value; }
			get{ return (MyClass)Dictionary[id];}
		}
	}

Das Programm:

Code:
class Class1
	{
		static void Main(string[] args)
		{
			MyHashtable ht = new MyHashtable();
			ht.Add(new MyClass(1234567,11,12,13,14,15));
			ht.Add(new MyClass(2234567,21,22,23,24,25));
			ht.Add(new MyClass(3234567,31,32,33,34,35));
			ht.Add(new MyClass(4234567,41,42,43,44,45));
			ht.Add(new MyClass(5234567,51,52,53,54,55));

			Console.WriteLine(ht[4234567].Wert1.ToString());
			Console.WriteLine(ht[4234567].Wert2.ToString());
			Console.WriteLine(ht[4234567].Wert3.ToString());
			Console.WriteLine(ht[4234567].Wert4.ToString());
			Console.WriteLine(ht[4234567].Wert5.ToString());
			Console.ReadLine();
		}
       }
 
Ok ich glaub ich versteh wie du das meinst. Ich mache eine klasse mit Eigenschaften Key und Werten. Dann mach ich eine neue Klasse Hashtable, das mir (auch) die methode Add überschreibt, damit ich dann Elemente meiner Klasse in die HT klasse einfügen kann. Finden kann ich dann das Element in der Ht mit dem key, und die Werte ansprechen kann ich über die eigenschaften des Ht-Keys (sozusagen)....super. Schaut sehr gut aus, danke. Glaubst du ist das dann wirklich schneller als meine Methode? Ich frage ernsthaft, weil ichs nicht weiss. Deine ist auf jeden Fall schon mal eleganter :)
 
Ich denke schon, dass es um einiges schneller als ein vierdimensionales Array mit je 10.000.000 Werten ist :)
Kannst ja mal die Zeit messen wenn du Lust hast...

Jedenfalls ist es denke ich auch einfacher im Code zu handhaben..
 
ja....schon...aber das das Array 10.000.000 Werte hat ist ja im Prinzip egal - wenn ich den Wert von 1234567 holen will dann schreib ich einfach

Wert = Array(1234567,1)

...und ich nehm an der Compi springt einfach (so wie im Hashtable) zum Index 1234567 und geht nicht von Array(0,1) bis Array(1234567,1) alle Schlüssel durch...

Also das Anlegen des Arrays wird warscheinlich langsamer sein, aber dann, die Arbeit damit?

Aber egal, dein Code hat sowieso einige andere Vorzüge (z.b.: Werte unterschiedlicher Datentypen sind möglich, im Array nicht), das ich das sowieso verwenden werde ;-)
 
Zurück