我想编写一个简单的程序来减轻工作负担,但是我对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){
}
}
我还不了解如何保存经过修改的行的新文件。
答案 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
)作为参数。在每次迭代中,它决定是否应跳过新项目b
(diff < 10
),将其添加到去重复列表(diff==10
)还是将其合并(diff > 10
)。这里要理解的关键是b
始终是可枚举中的下一项,并且从当前迭代返回的值将成为下一个迭代的当前值(a
)。换句话说,a
代表每次迭代函数执行的结果。
覆盖源文件通常不是一个好主意(除非您已将其备份到某个地方),所以我将输出到一个新文件,但是您可以根据需要进行更改。
这也是一个简单的例子。确保考虑诸如文件无行之类的情况。