在 VB.NET 中比较数组
Posted
技术标签:
【中文标题】在 VB.NET 中比较数组【英文标题】:Comparing arrays in VB.NET 【发布时间】:2009-05-20 13:48:41 【问题描述】:在我进入问题的具体细节之前,让我提供一些细节来解释我想要完成的工作。
我有两个数据源——一个是包含部件号、描述等的 SQL Server。另一个是没有传统意义上的数据库的 CAD 系统。我要做的是从 SQL Server 中读取物料清单,并将其与 CAD 装配图进行比较,以确保 CAD 系统包含与 SQL Server 相同的信息。
从 SQL Server 获取数据非常简单。我查询数据库并填充数据网格。完毕。快的。很简单。
从 CAD 系统获取数据的过程稍微复杂一些。我必须加载装配图以获取所有零部件的列表,然后加载这些单独的图纸以从图纸中提取“零件编号”属性。这是一个耗时且缓慢的过程(不幸的是),因为必须实际访问每个文件。我将这些属性加载到一个数组中(我想一个列表可能更有效)。
所以现在我有一个带有零件编号的数据网格和数组。我需要比较它们并相应地为网格着色。如果部件存在于两者中,则网格应保持透明,如果仅存在于网格中,则将行着色为黄色,如果仅存在于数组中,则添加红色行。
据我所知,这意味着在网格的每一行上循环遍历数组。思路是这样的:
-
默认网格为黄色行。
遍历网格并遍历数组进行比较。如果找到匹配项,则使该行透明并从数组中删除该元素。
步骤 2 完成后,数组应该只包含在网格中找不到的元素。调整数组大小以移除空元素。
将数组元素添加到网格中,并将这些新行涂成红色。
这种逻辑的问题在于从性能的角度来看它似乎很昂贵。肯定有更好的方法吗?此外,如果我以某种方式(如度假村)修改网格,我必须再次完成该过程。我非常感谢您对此提出建议。
谢谢!
注意:用 Visual Studio 2005 编写。
【问题讨论】:
【参考方案1】:您可以将 CAD 系统中的数据加载到字典中(按零件编号索引)。然后你可以遍历网格并检查它是否存在于字典中,这是一个快速操作( O(1) )。你可以完全按照你说的做,删除字典中找到的元素并将剩余的元素添加到数据网格中。
这里有一些用于创建和使用字典的代码(使用 C# 样式的 cmets 来保留格式):
//First argument is your key type, second is your item type
Dim cadParts As New Dictionary(Of Integer, Part)
//Add items to the parts dictionary
For Each part As Part In cadPartsArray
cadParts.Add(part.PartNumber,part)
Next
//Check if a part exists
Dim partNumber As Integer = 12345
If cadParts.ContainsKey(partNumber) ...
//Remove a part
cadParts.Remove(partNumber)
//Go through the remaining values
For Each part As Part In cadParts.Values ...
编辑:
1) 是的,如果您的键(此处为部件号)是字符串,那么将使用 Dictionary(Of String,...)。
2) 我假设您有一个名为 Part 的类,其中包含有关零件的一些信息。如果您只有一个零件号,而没有其他信息,那么您可以创建一个 Hashset。它与字典基本相同,但在这种结构下,值也是您的键。你会像这样创建一个哈希集:
Dim cadParts As New Hashset(Of String)
我不会通过代码示例,因为它非常接近字典。 ContainsKey 变为 Contains,而 Add 仅接受一个参数(此处为您的部件号)。
3) 是的,遍历它们并将它们添加到哈希集中。
【讨论】:
正是我的想法。好简洁的解释。 谢谢。我做了一些探索,听起来按照你的建议做会更快。不过说实话,我是一个新手 .NET 开发人员,所以我以前没有使用过字典。能否提供一个创建字典函数的代码示例? 感谢代码示例。几个问题 - 1)当你创建字典时 - 我的零件号是字符串。我认为这意味着它应该是“字符串”,对吗? 2)您列为“部分”的第二个参数需要一个类型。我不明白你为什么把“部分”放在那里。不应该是字符串吗?我得到的印象是 Part 是一个已经假设我创建的对象。 3)我的数组函数只返回一个零件编号列表。所以我假设我只是遍历它并将它输入到我的字典中,对吗? 谢谢 - 我认为这对于我需要做的事情来说很好。似乎也比较快。 :) 附带说明,hashset 在 VS 2005 (.NET 2.0) 中不可用。我想这一定是 3.5 的事情。【参考方案2】:如果零件编号是唯一的(在您要搜索的值中没有重复),那么您可以使用排序字典。然后删除重复项并使用剩余的项目。
要比较,您可以使用以下零件编号:
if(dictionary.ContainsKey(partNumber))
dictionary.Remove(partNumber)
end if
【讨论】:
【参考方案3】:鉴于一次只能看到一定数量的数据网格行,在 OnPaint 方法中实现一些代码可能会更快(我在这里有点生疏,如果不是,请道歉完全正确)对于每行检查零件信息数组并设置每行的背景颜色,因为它变得可见,甚至可能将每行标记为已处理,因此不需要重复操作。与一次处理所有行相比,这里可能会获得初始性能提升。
没有真正的相关性;但从以前的经验来看,这听起来像是在与 AutoDESK Inventor 文件交互?
【讨论】:
你是对的。这是使用 Apprentice Server 与 Inventor 11 的结合。我对你关于“油漆”的建议很感兴趣。考虑到如果用户使用网格会更加健壮,我认为这有很多优点。问题是如何处理网格中不存在的数组元素? 这些会是第 4 步中描述的“红色”行吗?您可能会遇到我过去遇到的一个问题,即想向绑定到数据源的数据网格添加更多行,我认为过去我已经通过使用 FlexGrid 解决了这个问题,并且用数据填充它,应该可以在计算缺失的内容时添加“红色”行。【参考方案4】:另一种解决方案可能是实现 IComparable(Of T) 接口
这需要您构建一个用于这两种情况的类。
Public Class Item
Implements IComparable(Of Item)
Private _Description As String
Public Property Description() As String
Get
Return _Description
End Get
Set(ByVal value As String)
_Description = value
End Set
End Property
Private _PartNo As Integer
Public Property PartNo() As Integer
Get
Return _PartNo
End Get
Set(ByVal value As Integer)
_PartNo = value
End Set
End Property
Public Function CompareTo(ByVal other As Item) As Integer Implements System.IComparable(Of Item).CompareTo
' Your rules for comparing content for objects
If other.PartNo <> Me.PartNo Then Return 1
If other.Description <> Me.Description Then Return 1
' Return 0 if the object are the same
Return 0
End Function
End Class
这是一个适用于上层实现的小测试。
Dim item As New Item
item.Description = "Desc"
item.PartNo = 34
Dim item2 As New Item
item2.Description = "Desc"
item2.PartNo = 35
Dim item3 As New Item
item3.Description = "Desc"
item3.PartNo = 36
Dim listFromDatabase As New Generic.List(Of Item)
listFromDatabase.Add(item)
listFromDatabase.Add(item2)
If listFromDatabase.Contains(item2) Then
MessageBox.Show("item2 was found in list")
End If
If Not listFromDatabase.Contains(item3) Then
MessageBox.Show("item3 was NOT found in list")
End If
希望对你有所帮助, - 丹
【讨论】:
我认为你有一个简洁的概念。不幸的是,我认为我太新手了,无法使用它。看起来它让我能够存储多个数据点(这很棒)。不幸的是,我在您的测试中没有得到项目类的多个实例化。此外,我只想在我的数据库部件号和 cad 部件号之间进行字符串比较。所以我不确定这对你的例子有什么影响。以上是关于在 VB.NET 中比较数组的主要内容,如果未能解决你的问题,请参考以下文章
VB.net 创建日期 Killswitch(比较两个日期)