基于 VB.Net 的 DataTable 中的行项目删除重复行的最佳方法是什么?
What's The Best Way To Remove Duplicate Rows Based On A Row Item In A DataTable With VB.Net?
在互联网上阅读了多个 post 后,我无法弄清楚如何做到这一点,我只想在下面就这个问题做一个非常明确的 post。
如果有人指出有相同问题的文章对我有帮助,我将删除 post。
下面有一个示例数据 table。我想删除重复的行,但仅在 "Request Type" 为 "Cancel Order" 且 "Order Numbers" 相同的情况下。
Report Date Time, Order Number, Request Type, Old Value, New Value
12/5/2019 12:00 , TM123456-01 , Cancel Order, 470000000, 5700000000
12/5/2019 12:00 , TM123456-01 , Cancel Order , 123000000, 4560000000
12/5/2019 12:00 , MT123456-02 , Add Order , 470000000, 5700000000
12/5/2019 12:00 , AP123456-02 , Add Order , 470000000, 5700000000
12/5/2019 12:00 , ST123456-02 , Remove Order , 470000000, 5700000000
所以应该从上面的数据 table 中删除的行应该是第 2 行,因为它与第 1 行 "TM123456-01" 具有相同的 "Order Number" 并且它的请求类型是"Cancel Order".
我希望得到的结果是下面的数据 table。
Report Date Time, Order Number, Request Type, Old Value, New Value
12/5/2019 12:00 , TM123456-01 , Cancel Order, 470000000, 5700000000
12/5/2019 12:00 , MT123456-02 , Add Order , 470000000, 5700000000
12/5/2019 12:00 , AP123456-02 , Add Order , 470000000, 5700000000
12/5/2019 12:00 , ST123456-02 , Remove Order , 470000000, 5700000000
我知道我可能可以使用嵌套的 For Each 循环来执行此操作,但我想了解如何使用 Microsoft LINQ(如果可能)或其他方法以更优雅的方式执行此操作。
C#版本:
var result = orders.GroupBy(x => new { x.OrderNumber, x.RequestType})
.SelectMany(x => x.Key.RequestType=="Cancel Order" ? x.Take(1) : x.ToList());
假设您要删除原始 table 中的行,而不是创建新的 table,您可以使用 LINQ 找到要删除的行,然后删除它们。 LINQ 用于查询数据,而不是修改数据。
Dim indicesOfRowsToDelete = dt.AsEnumerable _
.Select(Function(r, n) New With { Key r, Key n }) _
.GroupBy(Function(rn) New With { Key .OrderNumber = rn.r.Field(Of String)("OrderNumber"), Key .RequestType = rn.r.Field(Of String)("RequestType") }) _
.Where(Function(rg) rg.Key.RequestType = "Cancel Order") _
.SelectMany(Function(rg) rg.Skip(1).Select(Function(rn) rn.n)) _
.OrderByDescending(Function(n) n)
For Each n In indicesOfRowsToDelete
dt.Rows(n).Delete
Next
这是相同代码的 C# 版本:
var indicesOfRowsToDelete = dt.AsEnumerable()
.Select((r, n) => new { r, n })
.GroupBy(rn => new { OrderNumber = rn.r.Field<string>("OrderNumber"), RequestType = rn.r.Field<string>("RequestType") })
.Where(rg => rg.Key.RequestType == "Cancel Order")
.SelectMany(rg => rg.Skip(1).Select(rn => rn.n))
.OrderByDescending(n => n);
foreach (var n in indicesOfRowsToDelete)
dt.Rows[n].Delete();
但是,由于您发布的解决方案创建了一个包含所需行的新 table,这里是一个 LINQ 查询,用于在 C# 中创建一个新的 DataTable
:
var newDT = dt.AsEnumerable()
.GroupBy(r => new { OrderNumber = r.Field<string>("OrderNumber"), RequestType = r.Field<string>("RequestType") })
.SelectMany(rg => rg.Key.RequestType == "Cancel Order"
? rg.Take(1) // or other selection process
: rg
)
.CopyToDataTable();
我为解决这个问题所做的是一个函数,它传入一个数据 Table 并输出一个数据 Table,其中包含我想要删除的重复项。
我使用 For Each 循环和 if 语句删除了重复项。我仍然相信应该有一种方法可以用 Linq 做到这一点。如果您 post 一个答案,我们将不胜感激,但现在,我会 post 我在下面。
请注意数据Table是输入和输出参数,因此它们不会在我的工作流程中声明。
Dim ListOfOrderNumbers As New List(Of String)
ForEach row in DataTable1
If row.Item("RequestType").ToString = "Cancel Order" Then
If ListOfOrderNumbers.Contains(row.Item("OrderNumber").ToString) Then
'Do nothing
Else
DataTable2.Rows.Add(row.Item("ReportDateTime"), row.Item("OrderNumber").ToString, row.Item("RequestType").ToString, row.Item("OldValue").ToString, row.Item("NewValue").ToString)
'Add the row to DataTabe2 since we know the order number is not in it yet.
ListOfOrderNumbers.Add(row.Item("OrderNumber").ToString)
'Add the OrderNumber to ListOfOrderNumbers so a row with the same OrderNumber doesn't get added to DataTable2 again.
Else
DataTable2.Rows.Add(ReportDateTime, OrderNumber, RequestType, OldValue, NewValue)
在互联网上阅读了多个 post 后,我无法弄清楚如何做到这一点,我只想在下面就这个问题做一个非常明确的 post。
如果有人指出有相同问题的文章对我有帮助,我将删除 post。
下面有一个示例数据 table。我想删除重复的行,但仅在 "Request Type" 为 "Cancel Order" 且 "Order Numbers" 相同的情况下。
Report Date Time, Order Number, Request Type, Old Value, New Value
12/5/2019 12:00 , TM123456-01 , Cancel Order, 470000000, 5700000000
12/5/2019 12:00 , TM123456-01 , Cancel Order , 123000000, 4560000000
12/5/2019 12:00 , MT123456-02 , Add Order , 470000000, 5700000000
12/5/2019 12:00 , AP123456-02 , Add Order , 470000000, 5700000000
12/5/2019 12:00 , ST123456-02 , Remove Order , 470000000, 5700000000
所以应该从上面的数据 table 中删除的行应该是第 2 行,因为它与第 1 行 "TM123456-01" 具有相同的 "Order Number" 并且它的请求类型是"Cancel Order".
我希望得到的结果是下面的数据 table。
Report Date Time, Order Number, Request Type, Old Value, New Value
12/5/2019 12:00 , TM123456-01 , Cancel Order, 470000000, 5700000000
12/5/2019 12:00 , MT123456-02 , Add Order , 470000000, 5700000000
12/5/2019 12:00 , AP123456-02 , Add Order , 470000000, 5700000000
12/5/2019 12:00 , ST123456-02 , Remove Order , 470000000, 5700000000
我知道我可能可以使用嵌套的 For Each 循环来执行此操作,但我想了解如何使用 Microsoft LINQ(如果可能)或其他方法以更优雅的方式执行此操作。
C#版本:
var result = orders.GroupBy(x => new { x.OrderNumber, x.RequestType})
.SelectMany(x => x.Key.RequestType=="Cancel Order" ? x.Take(1) : x.ToList());
假设您要删除原始 table 中的行,而不是创建新的 table,您可以使用 LINQ 找到要删除的行,然后删除它们。 LINQ 用于查询数据,而不是修改数据。
Dim indicesOfRowsToDelete = dt.AsEnumerable _
.Select(Function(r, n) New With { Key r, Key n }) _
.GroupBy(Function(rn) New With { Key .OrderNumber = rn.r.Field(Of String)("OrderNumber"), Key .RequestType = rn.r.Field(Of String)("RequestType") }) _
.Where(Function(rg) rg.Key.RequestType = "Cancel Order") _
.SelectMany(Function(rg) rg.Skip(1).Select(Function(rn) rn.n)) _
.OrderByDescending(Function(n) n)
For Each n In indicesOfRowsToDelete
dt.Rows(n).Delete
Next
这是相同代码的 C# 版本:
var indicesOfRowsToDelete = dt.AsEnumerable()
.Select((r, n) => new { r, n })
.GroupBy(rn => new { OrderNumber = rn.r.Field<string>("OrderNumber"), RequestType = rn.r.Field<string>("RequestType") })
.Where(rg => rg.Key.RequestType == "Cancel Order")
.SelectMany(rg => rg.Skip(1).Select(rn => rn.n))
.OrderByDescending(n => n);
foreach (var n in indicesOfRowsToDelete)
dt.Rows[n].Delete();
但是,由于您发布的解决方案创建了一个包含所需行的新 table,这里是一个 LINQ 查询,用于在 C# 中创建一个新的 DataTable
:
var newDT = dt.AsEnumerable()
.GroupBy(r => new { OrderNumber = r.Field<string>("OrderNumber"), RequestType = r.Field<string>("RequestType") })
.SelectMany(rg => rg.Key.RequestType == "Cancel Order"
? rg.Take(1) // or other selection process
: rg
)
.CopyToDataTable();
我为解决这个问题所做的是一个函数,它传入一个数据 Table 并输出一个数据 Table,其中包含我想要删除的重复项。
我使用 For Each 循环和 if 语句删除了重复项。我仍然相信应该有一种方法可以用 Linq 做到这一点。如果您 post 一个答案,我们将不胜感激,但现在,我会 post 我在下面。
请注意数据Table是输入和输出参数,因此它们不会在我的工作流程中声明。
Dim ListOfOrderNumbers As New List(Of String)
ForEach row in DataTable1
If row.Item("RequestType").ToString = "Cancel Order" Then
If ListOfOrderNumbers.Contains(row.Item("OrderNumber").ToString) Then
'Do nothing
Else
DataTable2.Rows.Add(row.Item("ReportDateTime"), row.Item("OrderNumber").ToString, row.Item("RequestType").ToString, row.Item("OldValue").ToString, row.Item("NewValue").ToString)
'Add the row to DataTabe2 since we know the order number is not in it yet.
ListOfOrderNumbers.Add(row.Item("OrderNumber").ToString)
'Add the OrderNumber to ListOfOrderNumbers so a row with the same OrderNumber doesn't get added to DataTable2 again.
Else
DataTable2.Rows.Add(ReportDateTime, OrderNumber, RequestType, OldValue, NewValue)