c# Datatable(删除彼此之间 60 秒内的重复记录,仅保留第一条)
c# Datatable ( deleting Duplicate records within 60 seconds of each other , keeping only the first )
我有一个包含三个字段的 C# 数据table。我只想在之后的其他类似记录中保留输入时间超过 60 秒的第一条记录。
类似被定义为:
除上述条件外,ID 号和帐单代码必须相同才能在最终 table 中排除。
所以我下面的例子是输入
|IdNumber(字符串)|EntryDate(日期时间)|BillingCode(Int) |
| 5678 | 2021/06/16 08:46:37 | 56 |
| 5678 | 2021/06/16 08:46:54 | 56 |
| 5678 | 2021/06/16 08:47:16 | 56 |
| 5678 | 2021/06/16 08:47:54 | 56 |
| 5678 | 2021/06/16 08:47:59 | 57 |
| 5691 | 2021/06/16 08:47:59 | 57 |
| 5694 | 2021/06/16 08:48:00 | 57 |
结果输出应该类似于
|IdNumber(字符串)|EntryDate(日期时间)|BillingCode(Int) |
| 5678 | 2021/06/16 08:46:37 | 56 |
| 5678 | 2021/06/16 08:47:54 | 56 |
| 5678 | 2021/06/16 08:47:59 | 57 |
| 5691 | 2021/06/16 08:47:59 | 57 |
| 5694 | 2021/06/16 08:48:00 | 57 |
在过去的一天里,我一直在为此苦苦挣扎,无法解决问题。
Linq 或 Datatable select 查询有什么建议吗?
约翰
简单的 Linq 查询为:
var toDelete =
stuff.GroupBy(x => new { x.IdNumber, x.BillingCode })
.SelectMany(g =>
g.OrderBy(x => x.EntryDate)
.Aggregate(
new { toKeep = new List<Thing>(), toDelete = new List<Thing>() },
(acc, record) =>
{
var shouldDeleteRecord =
acc.toKeep.Any(x => x.EntryDate.AddSeconds(60) > record.EntryDate);
if (shouldDeleteRecord)
{
acc.toDelete.Add(record);
}
else
{
acc.toKeep.Add(record);
}
return acc;
}
).toDelete
);
// todo: delete your stuff here
我们的想法是,按 IdNumber 和 BillingCode 对它们进行分组,然后按进入日期对它们进行排序。遍历每个有序组中的每个项目,并保留第一个在最后一个强加的 60 秒边界之外的项目。删除其余部分。
如果将其编写为循环而不是仅使用 Linq,会更简洁,也更易于维护。
编辑:抱歉,忘了说,我正在使用 Thing
来代替您的数据名称:
class Thing
{
public DateTime EntryDate { get; set; }
public string IdNumber { get; set; }
public int BillingCode { get; set; }
}
和stuff
是一个IEnumerable<Thing>
(代表你的table)。
我有一个包含三个字段的 C# 数据table。我只想在之后的其他类似记录中保留输入时间超过 60 秒的第一条记录。
类似被定义为:
除上述条件外,ID 号和帐单代码必须相同才能在最终 table 中排除。
所以我下面的例子是输入
|IdNumber(字符串)|EntryDate(日期时间)|BillingCode(Int) |
| 5678 | 2021/06/16 08:46:37 | 56 |
| 5678 | 2021/06/16 08:46:54 | 56 |
| 5678 | 2021/06/16 08:47:16 | 56 |
| 5678 | 2021/06/16 08:47:54 | 56 |
| 5678 | 2021/06/16 08:47:59 | 57 |
| 5691 | 2021/06/16 08:47:59 | 57 |
| 5694 | 2021/06/16 08:48:00 | 57 |
结果输出应该类似于
|IdNumber(字符串)|EntryDate(日期时间)|BillingCode(Int) |
| 5678 | 2021/06/16 08:46:37 | 56 |
| 5678 | 2021/06/16 08:47:54 | 56 |
| 5678 | 2021/06/16 08:47:59 | 57 |
| 5691 | 2021/06/16 08:47:59 | 57 |
| 5694 | 2021/06/16 08:48:00 | 57 |
在过去的一天里,我一直在为此苦苦挣扎,无法解决问题。
Linq 或 Datatable select 查询有什么建议吗?
约翰
简单的 Linq 查询为:
var toDelete =
stuff.GroupBy(x => new { x.IdNumber, x.BillingCode })
.SelectMany(g =>
g.OrderBy(x => x.EntryDate)
.Aggregate(
new { toKeep = new List<Thing>(), toDelete = new List<Thing>() },
(acc, record) =>
{
var shouldDeleteRecord =
acc.toKeep.Any(x => x.EntryDate.AddSeconds(60) > record.EntryDate);
if (shouldDeleteRecord)
{
acc.toDelete.Add(record);
}
else
{
acc.toKeep.Add(record);
}
return acc;
}
).toDelete
);
// todo: delete your stuff here
我们的想法是,按 IdNumber 和 BillingCode 对它们进行分组,然后按进入日期对它们进行排序。遍历每个有序组中的每个项目,并保留第一个在最后一个强加的 60 秒边界之外的项目。删除其余部分。
如果将其编写为循环而不是仅使用 Linq,会更简洁,也更易于维护。
编辑:抱歉,忘了说,我正在使用 Thing
来代替您的数据名称:
class Thing
{
public DateTime EntryDate { get; set; }
public string IdNumber { get; set; }
public int BillingCode { get; set; }
}
和stuff
是一个IEnumerable<Thing>
(代表你的table)。