2010-10-26 11 views
1

Quel serait le moyen le plus rapide de stocker Liste de type Point, dans une chaîne qui produit minimum longueur de chaîne et avec l'algorithme d'analyse plus rapide retour? J'ai trouvé que le framework a les méthodes Convert.ToBase64String et Convert.FromBase64String. Ouvert à toutes les idées à l'aide de ceux-ci ou encore mieux auto algorithmes conçus;)Meilleure façon de stocker la liste <Point> dans une chaîne et analyser

Merci à l'avance

C#, VS2005 (.net 2.0)

-Edit-

Je vais utiliser le code un composant activeX et je ne peux pas ajouter une autre bibliothèque juste à cet effet.

+0

Ces points sont-ils des points 2D avec des valeurs X et Y? Y a-t-il des limites pour ces points? – idursun

+0

@idursun ils sont réellement des coordonnées d'image, donc je suppose que jamais plus de 65536 (deux octets) – honibis

+0

Les images ne sont pas limitées à seulement 16 bits dimensions. Cela peut être vrai pour certains formats d'image, mais les fichiers PNG et TIFF utilisent 32 bits pour définir les dimensions. Une analyse d'une trame de film 4x5 donnera un fichier qui a plus de 120 000 pixels sur la longue dimension. –

Répondre

2

Utiliser la représentation hexagonale de ints, il réduit la taille de la chaîne:

sérialisation:

List<Point> list = new List<Point>(new Point[] {new Point(1, 2), new Point(10, 20), new Point (100, 200), new Point(1000, 2000), new Point(10000, 20000)}); 

// 1. To. 
StringBuilder sb = new StringBuilder(); 
foreach (Point point in list) 
{ 
    sb.Append(Convert.ToString(point.X, 16));sb.Append('.'); 
    sb.Append(Convert.ToString(point.Y, 16));sb.Append(':'); 
} 

string serialized = sb.ToString(); 

Voici la chaîne de rm: "xy: 1,2: A.14: 64.c8: 3e8.7d0: 2710.4e20:"

Deserialize, fendage ('sérialisé' est la chaîne contient la chaîne de nombres):

string[] groups = serialized.Split(new char[] {':'}, StringSplitOptions.RemoveEmptyEntries); 
foreach (string group in groups) 
{ 
    string[] coords = group.Split('.'); 
    restored.Add(new Point(Convert.ToInt32(coords[0], 16), Convert.ToInt32(coords[1], 16))); 
} 

Ou vous pourriez vous demander d'analyser des groupes ("[0-9a-fA-F]. [0-9a-fA-F]"), c'est à vous de décider. Je ne suis pas sûr de ce qui est le plus rapide.

ou d'une simple machine d'état (juste pour le plaisir):

List<Point> restored = new List<Point>(); 
string value = default(string); 
int left = 0; 
int x = 0, y = 0; 
for (int i = 0; i < serialized.Length; i++) 
{ 
    if (serialized[i] == '.') 
    { 
     value = serialized.Substring(left, i - left); 
     left = i + 1; 
     x = Convert.ToInt32(value, 16); 
    } 
    else if (serialized[i] == ':') 
    { 
     value = serialized.Substring(left, i - left); 
     left = i + 1; 
     y = Convert.ToInt32(value, 16); 
     restored.Add(new Point(x, y)); 
    } 
} 

à mon humble avis. EDITED: Ou mieux encore d'empaqueter des entiers à des groupes d'hex: 1212 à 'CC' comme il est utilisé dans les anciens systèmes financiers; cela fait deux fois moins de longueur de corde.

+0

+1 Je cherchais des idées comme celle-ci. Utiliser une chaîne plus efficacement avec hex est un bon point. – honibis

1

Comment utiliser JSON?

+0

Oui, JSON est simple à analyser et sérialiser. Il n'ajoute pas beaucoup de caractères supplémentaires à la chaîne non plus. Codeplex a de bons sérialiseurs/désérialiseurs. – jgauffin

1

En toute honnêteté, il est presque impossible de répondre à cette autorité. Tout dépend de la taille de la liste de points, si elle doit vraiment être une chaîne, et quel aspect vous essayez d'optimiser. Par exemple, si vous avez besoin de la vitesse brute, vous pouvez échanger de la mémoire RAM pour le temps de traitement, mais si vous avez besoin de vous devez avoir un algorithme qui ne consomme pas trop de ressources.

La manière la plus compacte et la plus rapide de stocker une liste de n'importe quoi et de restaurer la liste ultérieurement est d'utiliser la numérotation binaire. Bien sûr, cela vous laisse le risque qu'une modification du CLR puisse rendre le fichier inutilisable. Pour quiconque est intéressé, la sérialisation n'est efficace ni à partir de la vitesse ni à partir des concordances spatiales, mais le format peut être lu par d'autres CLR sans changement.

Les algorithmes Base64 sont assez efficaces et utilisent un algorithme de recherche de table de codes très rapide. Base64 encodant le format binaire peut donner de très bons résultats. Mais si vous n'avez pas besoin de le stocker comme une chaîne, pourquoi passer par le problème supplémentaire? CORBA définit également un algorithme binaire à chaîne qui doit être efficace pour les types de choses qu'il essaie de faire. Si je me souviens bien, il utilise un tableau de 128 symboles (c'est-à-dire un codage à 128 bits) donc plus compact que la base 64.

Finalement, vous devrez effectuer quelques tests. Avant de commencer vos tests, vous devez savoir quand l'algorithme est assez bon. À quel point la taille de la chaîne doit-elle être petite avant d'être acceptable? Juste à quelle vitesse l'algorithme d'analyse doit être avant qu'il ne soit acceptable. Et combien d'entre elles avez-vous besoin d'analyser simultanément? Vous seul pouvez le déterminer.

2

à cordes:

MYSTRING = string.Join("", list.Select( 
    point => point.x.toString("X").PadLeft(4, '0') + 
       point.y.toString("X").PadLeft(4, '0')).toArray()) 

partir d'une chaîne:

new Regex("(.{8})").Split(MYSTRING).Where(x => !string.IsNullOrEmpty(x)). 
    Select(x=> new Point(x.Take(4), x.Skip(4).Take(4))) 
+0

N'oubliez pas d'ajouter un support de séparateur de chiffres spécifique à la culture – abatishchev

+0

Merci pour la réponse, mais linq n'est pas supporté par .net 2.0, et je peux avoir des longueurs de 1 à 5 chiffres qui entraîneront un gaspillage d'espace dû au rembourrage. – honibis

+0

Ensuite, vous devez utiliser des séparateurs entre les points et x et y à l'intérieur du point. Juste tester, ce qui produit moins de cordes dans votre cas. –

Questions connexes