C # CSV Filehelpers сравнивает две строки в одном файле, добавляет и удаляет строки - PullRequest
2 голосов
/ 29 мая 2019

Я хочу написать простую программу, которая облегчит мою жизнь на работе, но я не слишком знаком с C #, поэтому я пытаюсь прочитать документацию и некоторые примеры, но я не нахожу документацию слишком хорошей, и не могу найти ни одного примера.

У меня есть файл CSV (беспроводной датчик температуры, который иногда теряет соединение или отправляет несколько показаний в быстрой последовательности), и я хочу сравнить два DateTimes (TimeSpan) из 2 последовательных строк и в зависимости от результата удалить эту строку или добавить другую между ними. Если интервал времени между 2 датами и временем меньше 10 минут, удалите эту строку. Если оно длиннее 10 минут, создайте новую строку со временем, которое составляет 10 минут после первого. Все показания между собой кратны 10 минутам.

Файл примера:

[DelimitedRecord(","), IgnoreFirst(1)]
public class CSVDataFields{
  [FieldQuoted('"')] [FieldConverter(ConverterKind.Date, "MM/dd/yyyy h:mm tt")]
  public DateTime Date;
  [FieldQuoted('"')]
  public float Value;
}

"Date","Value"
"03/19/2019 3:10 PM","20.5"
"03/19/2019 3:10 PM","20.5"
"03/19/2019 3:10 PM","20.4"
"03/19/2019 3:20 PM","20.2"
"03/19/2019 3:50 PM","20.0"
"03/19/2019 4:00 PM","19.8"

Итак, первая проверка - [0] и [1], меньше 10, поэтому удалите эту строку, [0] и [2] меньше 10 - удалите, [0] и [3] все в порядке,

[3] и [4] длиннее 10 минут, создайте новую строку со временем ([3] + 10) и средним значением (20,2, 20,0),

new [4] и [5] длиннее 10 минут, создайте новую строку со временем ([4] + 10) и средним значением (20.1, 20.0) и т. Д.

В примере на FileHelpers.net есть только этот пример. Я думаю, что здесь вы можете получить доступ только к 1 строке за раз, в то время как мне нужно иметь доступ к 2 строкам одновременно.

private void DetectDupes(ref CSVDataFields[] csv){
  foreach(CSVDataFields csvData in csv){

  }
}

Я также не дошел до того, как сохранить новый файл с измененными строками.

1 Ответ

1 голос
/ 29 мая 2019

Вы можете сделать это с помощью метода Aggregate Линка:

var engine = new FileHelperEngine<CSVDataFields>();

var result = engine.ReadFile(@"c:\temp\some_source_file.txt");

List<CSVDataFields> newRows = new List<CSVDataFields>();
newRows.Add(result.First());

result.Aggregate((a, b) =>
{
    var diff = Math.Abs((a.Date - b.Date).Minutes);
    if (diff < 10)
    {
        return a;
    }
    else if (diff == 10)
    {
        newRows.Add(b);
        return b;
    }
    else
    {
        var newRow = new CSVDataFields()
        {
            Date = a.Date.AddMinutes(10),
            Value = (a.Value + b.Value) / 2
        };
        newRows.Add(newRow);
        return newRow;
    }
});

engine.WriteFile(@"C:\temp\destination_file_deduped.txt", newRows);

Выход:

03/19/2019 15:10, 20,5

03/19/2019 15:20, 20,2

03/19/2019 15:30, 20,1

03/19/2019 15:40, 19,95

Пояснение: Метод Aggregate выполняет итерацию по перечислимому, выполняя делегат функции, который принимает в качестве параметров текущее значение (a) и следующее значение (b) для каждого элемента в перечислимом. На каждой итерации он решает, должен ли он пропустить новый элемент b (diff < 10), добавить его в дедуплицированный список (diff==10) или объединить (diff > 10). Здесь важно понять, что b - это всегда следующий элемент в перечислимом, а значение, возвращаемое из текущей итерации, становится текущим значением (a) следующей итерации. Другими словами, a представляет результат выполнения функции для каждой итерации.

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

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

...