在VB.NET中比较数组

4
在我开始讲解问题的实质之前,先提供一些细节。我有两个数据源——一个是包含零件编号、描述等信息的SQL Server,另一个是没有传统意义上的数据库的CAD系统。我的目标是从SQL Server中读取物料清单,并将其与CAD装配图进行比较,以确保CAD系统包含与SQL Server相同的信息。
从SQL Server获取数据相对简单。我查询数据库并填充数据网格。完成。快速。容易。
从CAD系统获取数据则需要更多的工作。我必须加载装配图以获取所有组件部件的列表,然后加载这些单独的图纸以从图纸中提取“零件编号”属性。这是一个有点耗时且缓慢的过程(不幸的是),因为每个文件都必须实际访问。我将这些属性加载到一个数组中(我想列表可能更有效)。
现在我有了一个带有零件号的数据网格和数组。我需要比较它们并相应地给网格着色。如果该零件存在于两个数据源中,则网格应保持透明;如果只存在于网格中,则将行颜色设置为黄色;如果只存在于数组中,则添加一行并将其颜色设置为红色。
据我所知,这意味着需要在网格的每一行中循环遍历数组。思路如下:
1. 将网格默认为黄色行。 2. 循环遍历网格并循环遍历数组进行比较。如果找到匹配项,则使该行透明并从数组中删除该元素。 3. 完成第2步后,数组应仅包含未在网格中找到的元素。调整数组大小以删除空元素。 4. 将数组的元素添加到网格中,并将这些新行颜色设置为红色。
这种逻辑的问题在于,从性能角度来看,它似乎很昂贵。肯定有更好的方法吧?此外,如果我以某种方式(如重新排序)修改网格,则必须再次执行此过程。我真的很需要一些建议。
谢谢!
注意:在Visual Studio 2005中编写。
4个回答

7
您可以将CAD系统的数据加载到字典中(按零件号索引)。然后,您可以遍历网格并检查它是否存在于字典中,这是一项快速操作(O(1))。您可以按照您所说的方式进行操作,从字典中删除找到的元素,并将剩余的元素添加到数据网格中。
以下是创建和使用字典的一些代码(使用C#样式注释以保留格式):
//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。它基本上与字典相同,但是在这种结构中,值也是您的键。您可以像这样创建一个hashset:

Dim cadParts As New Hashset(Of String)

我不会给出代码示例,因为它非常接近于字典。ContainsKey变成了Contains,而Add只接受一个参数(这里将是您的零件编号)。

3) 是的,循环遍历它们并将它们添加到哈希集中。


1
正是我所想的。简洁明了的解释。 - Demi
谢谢。我做了些调查,听起来按照您的建议处理会更快。但说实话,我是.NET开发的新手,之前从未使用过字典。是否可以提供一个创建字典函数的代码示例呢? - Mr Furious
感谢您提供的代码示例。我有几个问题:1)当您创建字典时,我的零件号是字符串。我认为这意味着它应该是“Of String”,对吗?2)您列出的第二个参数“part”需要一个类型。我不明白为什么要在那里放置“Part”。它不应该是字符串吗?我有一种印象,Part是一个已经假定我创建的对象。3)我的数组函数只返回零件号列表。所以我想我只需要循环遍历它并将其输入到我的字典中,对吗? - Mr Furious
谢谢!我认为这很适合我需要做的事情。而且看起来相对快速。 :) - Mr Furious
顺便提一下,在VS 2005(.NET 2.0)中没有可用的哈希集。我猜那一定是3.5的东西。 - Mr Furious

2
如果零件号是唯一的(在您要搜索的值中不重复),则可以使用排序字典。然后删除重复项并使用剩余的项目。
要进行比较,可以按以下方式使用零件号:
if(dictionary.ContainsKey(partNumber))
    dictionary.Remove(partNumber)
end if

2
考虑到数据网格一次只能显示一定数量的行,因此在OnPaint方法中实现一些代码可能更快。对于每一行,该代码将检查零件信息数组并在每一行变为可见时设置其背景颜色,甚至标记每一行已被处理,以便不需要重复操作。这里可能会有初始性能提升,超过一次性处理所有行的情况。
这与AutoDESK Inventor文件无关,仅供参考。

你说得对。这是使用Apprentice Server与Inventor 11相关的联系。我对你关于“on paint”的建议很感兴趣。考虑到用户重新排列网格时,它会更加强大。问题是如何处理在网格中不存在的数组元素? - Mr Furious
这些将是第4步中描述的“红色”行吗?您可能会遇到我过去遇到的问题,即想要向绑定到数据源的数据网格添加更多行。 我认为过去我通过使用FlexGrid并填充数据来解决了这个问题。在计算缺失内容时应该可以添加“红色”行。 - Richard

1

另一个解决方案可能是实现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

希望这能有所帮助, - 丹

我认为您有一个不错的概念。不幸的是,我认为自己太菜了,无法利用它。看起来它能让我存储多个数据点(这很棒)。但是,我不理解测试中item类的多次实例化。此外,我只希望在我的数据库部件编号和CAD零件编号之间进行字符串比较。所以我不确定这如何与您的示例相关。 - Mr Furious

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接