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

时间:2019-05-29 17:19:14

标签: c# csv datetime filehelpers

我想编写一个简单的程序来减轻工作负担,但是我对C#不太熟悉,因此我试图阅读文档和一些示例,但是我觉得文档不太好,并且找不到任何值得借鉴的例子。

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

[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){

  }
}

我还不了解如何保存经过修改的行的新文件。

1 个答案:

答案 0 :(得分:1)

您可以使用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);

输出:

  

2019/03/19下午3:10,20.5

     

03/19/2019 3:20 PM,20.2

     

2019/03/19下午3:30 20.1

     

2019/03/19下午3:40,19.95

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

覆盖源文件通常不是一个好主意(除非您已将其备份到某个地方),所以我将输出到一个新文件,但是您可以根据需要进行更改。

这也是一个简单的例子。确保考虑诸如文件无行之类的情况。