Ich habe eine dictionary<string, int[]>
, die ich so effizient wie möglich von der Festplatte speichern und abrufen muss.Der effizienteste Weg, um ein Wörterbuch in C# zu speichern/abzurufen?
Die Schlüssellänge (Zeichenfolge) wird normalerweise von 1 bis 60 Zeichen (Unicode) variieren, könnte aber diese Länge überschreiten (dies ist jedoch geringfügig und diese Werte könnten verworfen werden). Ganzzahlen im Array liegen im Bereich von 1 bis 100 Millionen. (In der Regel 1 bis 5 M)
Meine erste Idee, ein Format mit Trennzeichen zu verwenden, war:
key [tab] int,int,int,int,...
key2 [tab] int,int,int,int,...
...
und das Wörterbuch zu laden, wie folgt:
string[] Lines = File.ReadAllLines(sIndexName).ToArray();
string[] keyValues = new string[2];
List<string> lstInts = new List<string>();
// Skip the header line of the index file.
for (int i = 1; i < Lines.Length; i++)
{
lstInts.Clear();
keyValues = Lines[i].Split('\t');
if (keyValues[1].Contains(','))
{
lstInts.AddRange(keyValues[1].Split(','));
}
else
{
lstInts.Add(keyValues[1]);
}
int[] iInts = lstInts.Select(x => int.Parse(x)).ToArray();
Array.Sort(iInts);
dic.Add(keyValues[0], iInts);
}
Es funktioniert, aber gehen über die Mögliche Größenanforderungen, es ist offensichtlich, dass diese Methode nie gut genug skalieren wird.
Gibt es eine Standardlösung für dieses Problem oder muss ich den Algorithmus vollständig überarbeiten?
Edit: Ich bin ein wenig embarassed es zugeben, aber ich wusste nicht, Wörterbücher nur auf binäre serialisiert werden. Ich habe es getestet und es ist genau das, was ich gebraucht habe.
Hier ist der Code (Vorschläge willkommen)
public static void saveToFile(Dictionary<string, List<int>> dic)
{
using (FileStream fs = new FileStream(_PATH_TO_BIN, FileMode.OpenOrCreate))
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(fs, dic);
}
}
public static Dictionary<string, List<int>> loadBinFile()
{
FileStream fs = null;
try
{
fs = new FileStream(_PATH_TO_BIN, FileMode.Open);
BinaryFormatter bf = new BinaryFormatter();
return (Dictionary<string, List<int>>)bf.Deserialize(fs);
}
catch
{
return null;
}
}
Mit einem Wörterbuch von 100k Einträgen mit einer Reihe von 4k ganzen Zahlen, nimmt Serialisierung 14 Sekunden und Deserialisierung 10 Sekunden und die resultierende Datei ist 1,6 GB.
@Patryk: Bitte konvertieren Sie Ihren Kommentar zu einer Antwort, damit ich es als genehmigt markieren kann.
Mit "effizient" meinst du "size-effizient"? – Stefan
@Stefan - Größe/Geschwindigkeit scheint kein Problem zu sein, da OP es in Textdatei speichert ... Aber in der Tat ist es notwendig zu wissen, welche Art von "gut genug skalieren" benötigt wird, bevor es beantwortet werden kann. –
Wenige Seitennotizen; Anstatt Ihre Liste außerhalb der Schleife zu halten und sie ständig zu löschen, definieren Sie einfach die Liste innerhalb der Schleife. Wenn Sie eine Zeichenfolge ohne Trennzeichen aufteilen, wird nur ein Array der Größe 1 mit diesem Wert zurückgegeben. Sie müssen also nicht überprüfen, ob die Zeichenfolge "," enthält. Teilen Sie sie jedes Mal auf und fügen Sie alle Werte zur Liste hinzu "Alles" ist nur eins. Müssen Sie das Array sortieren? Wenn Sie eine vorhandene Struktur neu erstellen, warum sind sie nicht bereits sortiert? – Servy