【发布时间】:2020-12-02 10:44:33
【问题描述】:
我有两个具有相同结构的数据表。但其中的数据可能不同。
我需要一种快速的方法来检查数据是相同还是不同。我不需要知道有什么不同,因为其中一个是“新”数据表,另一个是“旧”数据表。如果存在差异,那么用户将不得不决定他想要新的还是旧的。
比较它们的好方法是什么?
我只知道逐个检查并比较它们,但必须有更快、更智能的方法。
【问题讨论】:
我有两个具有相同结构的数据表。但其中的数据可能不同。
我需要一种快速的方法来检查数据是相同还是不同。我不需要知道有什么不同,因为其中一个是“新”数据表,另一个是“旧”数据表。如果存在差异,那么用户将不得不决定他想要新的还是旧的。
比较它们的好方法是什么?
我只知道逐个检查并比较它们,但必须有更快、更智能的方法。
【问题讨论】:
当然你需要检查每个单元格,但你可以使用DataRowComparer.Equals:
Public Shared Function AreTablesEqual(t1 As DataTable, t2 As DataTable) As Boolean
If t1 Is Nothing AndAlso t2 Is Nothing Then Return True
If t1 Is Nothing OrElse t2 Is Nothing Then Return False
If t1.Columns.Count <> t2.Columns.Count Then Return False
If t1.Rows.Count <> t2.Rows.Count Then Return False
For i As Int32 = 0 To t1.Rows.Count - 1
If Not DataRowComparer.Default.Equals(t1.Rows(i), t2.Rows(i)) Then Return False
Next
Return True
End Function
如果有人搜索 C# 版本:
public static bool AreTablesEqual(DataTable t1, DataTable t2)
{
if (t1 == null && t2 == null) return true;
if (t1 == null || t2 == null) return false;
if (t1.Columns.Count != t2.Columns.Count || t1.Rows.Count != t2.Rows.Count) return false;
for (int i = 0; i < t1.Rows.Count; i++)
{
if (!DataRowComparer.Default.Equals(t1.Rows[i], t2.Rows[i])) return false;
}
return true;
}
【讨论】:
如果您将这两个表视为两组 DataRows(与接受的答案相反,顺序无关紧要),那么您可以使用 Enumerable.Except Method 使用 DataRowComparer.Default 作为相等比较器来确定不同的 DataRows .然后使用Enumerable.Any Method 确定是否发现任何差异。
Private Shared Function TableRowsAreTheSame(table1 As DataTable, table2 As DataTable) As Boolean
Dim bothNull As Boolean = table1 Is Nothing AndAlso table2 Is Nothing
Dim bothNotNull As Boolean = table1 IsNot Nothing AndAlso table2 IsNot Nothing
Dim equalColumnAndRowCounts As Func(Of Boolean) = Function() (table1.Rows.Count = table2.Rows.Count) AndAlso (table1.Columns.Count = table2.Columns.Count)
Dim equalFieldTypes As Func(Of Boolean) = Function()
Dim typeAreEqual As Boolean
For index As Int32 = 0 To table1.Columns.Count - 1
typeAreEqual = table1.Columns(index).DataType.Equals(table2.Columns(index).DataType)
If Not typeAreEqual Then Exit For
Next
Return typeAreEqual
End Function
Dim equalFieldValues As Func(Of Boolean) = Function()
' get rows in table1 that are Not in table2
Dim differringRows As IEnumerable(Of DataRow) = Enumerable.Except(table1?.AsEnumerable(), table2?.AsEnumerable(), DataRowComparer.Default)
Return (Not differringRows.Any)
End Function
Return bothNull OrElse
(bothNotNull AndAlso equalColumnAndRowCounts() AndAlso equalFieldTypes() AndAlso equalFieldValues())
End Function
【讨论】:
Not differringRows.Any(),而不是differringRows.Count() = 0。使用前者,您必须计算 所有 不同的行,而后者只检查是否有一个,这是您真正想知道的。
ICollection 的 Count 属性混淆,即 O(1)。但即使使用数组/列表,我也更喜欢Any,因为它更好地表达了意图。