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
表示函数每次迭代的执行结果。
覆盖源文件通常不是一个好主意(除非您将其备份在某处)所以我正在输出到一个新文件,但如果需要,您可以更改它。
此外,这是一个简单的示例。确保考虑到文件没有行等情况。
我想写一个简单的程序来缓解我的工作生活,但我对 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
表示函数每次迭代的执行结果。
覆盖源文件通常不是一个好主意(除非您将其备份在某处)所以我正在输出到一个新文件,但如果需要,您可以更改它。
此外,这是一个简单的示例。确保考虑到文件没有行等情况。