Лучший способ сохранить список <Point>в строку и разобрать обратно - PullRequest
1 голос
/ 26 октября 2010

Какой самый быстрый способ сохранить список типа Point в строке, которая выдает минимальную длину строки и с самым быстрым алгоритмом синтаксического анализа?

Я обнаружил, что в фреймворке есть Convert.Методы ToBase64String, Convert.FromBase64String.Открыты для любых идей с использованием этих или даже более качественных алгоритмов;)

Заранее спасибо

C #, vs2005 (.net 2.0)

-Edit-

Я буду использовать код в компоненте ActiveX и не могу добавить еще одну библиотеку только для этой цели.

Ответы [ 5 ]

3 голосов
/ 26 октября 2010

Использовать шестнадцатеричное представление целых чисел, оно уменьшает размер строки:

Сериализация:

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(); 

Вот строка в форме: "x.y: 1.2: a.14: 64.c8: 3e8.7d0: 2710.4e20:"

Десериализация, разбиение ('serialized' - строка содержит цепочку чисел):

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)));
}

Или вы можете регулярное выражение для анализа групп ("[0-9a-fA-F]. [0-9a-fA-F]"), решать вам. Я не уверен, что быстрее.

Или простой конечный автомат (просто для удовольствия):

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));
    }
}

ИМХО.

РЕДАКТИРОВАНИЕ: Или еще лучше упаковать целые числа в группы из шестнадцатеричных: от 1212 до 'CC', как это используется в старых финансовых системах; это делает длину строки в два раза меньше.

2 голосов
/ 26 октября 2010

В строку:

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

из строки:

new Regex("(.{8})").Split(MYSTRING).Where(x => !string.IsNullOrEmpty(x)).
     Select(x=> new Point(x.Take(4), x.Skip(4).Take(4)))
1 голос
/ 26 октября 2010

Просто используйте ProtoBuf.Net .

1 голос
/ 26 октября 2010

Честно говоря, почти невозможно ответить на этот вопрос авторитетно. Многое зависит от того, насколько велик список точек, действительно ли ему нужно , чтобы быть строкой, и какой аспект вы пытаетесь оптимизировать. Например, если вам нужна грубая скорость, вы можете обменять оперативную память на время обработки, но если вам нужна пропускная способность , вам нужен алгоритм, который не потребляет слишком много ресурсов.

Самый компактный и быстрый способ сохранить список чего угодно и восстановить его позже - использовать сериализацию binary . Конечно, это создает риск того, что изменение в CLR может сделать файл непригодным для использования. Для всех, кому это интересно, сериализация xml не эффективна ни по скорости, ни из соображений пространства, но формат может быть прочитан другими CLR без изменений.

Алгоритмы Base64 довольно эффективны и используют очень быстрый алгоритм поиска в таблице кодов. Кодирование Base64 в двоичном формате может дать очень хорошие результаты. Но если вам не нужно хранить его в виде строки, зачем делать лишние хлопоты?

CORBA также определяет двоичный алгоритм, который должен быть эффективен для типов вещей, которые он пытается сделать. Если я правильно помню, он использует таблицу кодов из 128 символов (то есть 128-битное кодирование), поэтому он более компактен, чем база 64.

В конце концов, вам придется выполнить несколько тестов. Перед тем, как начать тестирование, вы должны знать, когда алгоритм достаточно хорош . Насколько мал размер строки должен быть приемлемым? Насколько быстрым должен быть алгоритм разбора, прежде чем он станет приемлемым. И сколько из них вам нужно проанализировать одновременно? Только ты можешь это определить.

1 голос
/ 26 октября 2010

Как насчет использования JSON?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...