Эффективный метод для создания строки CSV из списков / SortedLists C #? - PullRequest
0 голосов
/ 13 декабря 2010

У меня есть приложение, которое реализует асинхронный SOAP. Каждые 50-100 мс я буду получать данные, которые преобразуются в SortedList<double,double> объект. У меня также есть предопределенный IList<double>, который содержит все возможные ключи в этом SortedList.

Мне нужно перебрать IList и проверить, содержит ли SortedList этот ключ. Если это так, я записываю это значение в строку csv; если нет, я пишу 0.0 в строку csv.

Примечание: IList имеет 400 ключей. SortedList, как правило, будет намного меньше, чем 400, максимум около 100.

        string MyText = timestamp.ToString("HH:mm:ss");
        for (int i = 0; i < AllKeys.Count; i++)
        {
            double info;
            if (MySortedList.TryGetValue(AllKeys[i], out info))
            {
                MyText += "," + info;
            }
            else
            {
                MyText += ",0.0";
            }
        }
        MyText += "\n";

        File.AppendAllText(filePath, MyText);

В настоящее время я использую приведенный выше код для создания строки csv перед записью ее в мой файл. Однако я обнаружил, что этот код отстает от моего приложения.

Мне нужна помощь для повышения эффективности, чтобы хранение входящих данных занимало менее 50 мс. Некоторые дополнительные вещи:

  • Мне не нужно писать в CSV-файл, мне просто нужно быстро сохранить данные. (Я могу преобразовать из сериализованного файла в мой CSV-файл позже)
  • Я рассмотрел вопрос об использовании LINQ, но я не знаком с запросами и не знаю, насколько эффективнее он будет

Редактировать: Я решил проблему с производительностью, предложив Конрадом создать объект StreamWriter. Я просто создал статический объект StreamWriter и записал в него весь свой текст перед закрытием StreamWriter, когда связь прервана.

Ответы [ 3 ]

2 голосов
/ 13 декабря 2010

Вот некоторые мысли.

1) Используйте StreamWriter для записи вместо файла.Это будет быстрее, чем два этапа записи в память, а затем в файл.

2) По возможности распараллелить работу.Например, если вы можете написать один поток для обработки сообщения, а другой поток - для написания сообщения.

3) Я не думаю, что цель LINQ - повысить производительность, но упростить манипуляции с данными

0 голосов
/ 13 декабря 2010

Я согласен с ответом Конрада - но еще одна идея для повышения производительности - сделать обратный поиск, т.е. взять каждый элемент из SortedList и выполнить поиск в другом списке (конечно, я бы порекомендовал иметь словарь вместо списка, чтобы быстреепоиск).

0 голосов
/ 13 декабря 2010

Я уверен, что не придумал самый эффективный алгоритм, но, по крайней мере, это отправная точка. Если ничего другого, вы заметите использование StringBuilder вместо объединения строк. Одно это, вероятно, принесет вам некоторое преимущество в производительности.

Этот алгоритм предполагает, что ключи SortedList и список «data» упорядочены одинаково (от низкого до высокого).

var textBuilder = new StringBuilder(timestamp.ToString("HH:mm:ss"));

var index = 0;
foreach(double key in data.Keys)
{
    while(Allkeys[index] < key)
    {
        textBuilder.Append(",0.0");
        index++;
    }

    textBuilder.Append(",").Append(data[key]);
    index++;
}
MyText = textBuilder.Append(@"\n").ToString();

Просто глядя на вышесказанное, я уверен, что есть ошибка, но не уверен, что или где, не тратя больше времени и / или тестирования.

Возможное решение LINQ является более декларативным:

var textBuilder = new StringBuilder(timestamp.ToString("HH:mm:ss"));

var values = Allkeys.Select(
    key => data.ContainsKey(key) ? data[key].ToString() : "0.0")
    .ToArray();

var data = String.Join(",", values);
var MyText = textBuilder.Append(data).Append(@"\n").ToString();

Еще можно включить в выражение LINQ, используя метод расширения Aggregate, но вам придется использовать конкатенацию строк в аккумуляторе, поэтому я не показал этого здесь.

...