C# CSV Filehelpers 比较同一文件中的两行,添加和删除行

C# CSV Filehelpers compare two rows in the same file, add and remove rows

我想写一个简单的程序来缓解我的工作生活,但我对 C# 不太熟悉,所以我试图阅读文档和一些示例,但我也没有找到文档很好,找不到任何例子供参考。

我有一个 CSV 文件(有时会断开连接或快速连续发送多个读数的无线温度传感器),我想比较两个后续行中的两个 DateTimes (TimeSpan),并根据结果删除该行,或者在这些之间添加另一个。如果 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) 创建一个新行,

新建[4]和[5]超过10分钟,新建一行,时间为([4]+10),平均值为(20.1,20.0),依此类推

在FileHelpers.net的例子中只有这个例子。我想在这里您一次只能访问 1 行,而我需要同时访问 2 行。

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

  }
}

关于如何保存包含修改后的行的新文件,我还没有弄清楚。

您可以使用 Linq 的 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 3:10 PM, 20.5

03/19/2019 3:20 PM, 20.2

03/19/2019 3:30 PM, 20.1

03/19/2019 3:40 PM, 19.95

解释: Aggregate 方法遍历可枚举,执行一个函数委托,该函数委托将可枚举中的每个项目的当前值 (a) 和下一个值 (b) 作为参数。在每次迭代中,它决定是否应该跳过新项目 b (diff < 10),将其添加到去重列表 (diff==10) 或合并它 (diff > 10)。这里要理解的关键是 b 始终是可枚举项中的下一项,并且从当前迭代返回的值成为下一次迭代的当前值 (a)。也就是说,a表示函数每次迭代的执行结果。

覆盖源文件通常不是一个好主意(除非您将其备份在某处)所以我正在输出到一个新文件,但如果需要,您可以更改它。

此外,这是一个简单的示例。确保考虑到文件没有行等情况。