2009-05-20 196 views
4

让我提供一些细节来解释我在尝试完成问题的细节之前要完成的工作。在VB.NET中比较数组

我有两个数据源 - 一个是包含部件号,描述等的SQL Server。另一个是CAD系统,没有传统意义上的数据库。我想要做的是从SQL Server中读出材料清单并将其与CAD装配图进行比较,以确保CAD系统包含与SQL Server相同的信息。

从SQL Server获取数据非常简单。我查询数据库并填充数据网格。完成。快。简单。

从CAD系统获取数据有一点涉及。我必须加载装配图以获得所有零部件的清单,然后加载这些独立的图纸以从图纸中拉出“零件号”属性。这是一个有点耗时和缓慢的过程(不幸),因为每个文件都必须实际访问。我将这些属性加载到数组中(我想列表可能更有效)。

所以,现在我有一个数据网格和数组与部分数字。我需要比较它们并相应地对网格着色。如果部件同时存在,网格应该保持透明;如果只存在于网格中,则将行变为黄色;如果仅存在于数组中,则添加一个红色的行。

尽我所知,这意味着循环遍历网格的每一行上的数组。思考过程如下:

  1. 默认网格为黄色行。
  2. 循环遍历网格并循环遍历数组进行比较。如果找到匹配项,则使该行透明并从数组中删除该元素。
  3. 第2步完成后,数组应该只包含在网格中找不到的元素。调整数组大小以删除空元素。
  4. 将数组的元素添加到网格,并将这些新行着色为红色。

这个逻辑的问题在于,从性能角度看它似乎很昂贵。当然有更好的方法?另外,如果我以某种方式修改网格(如度假村),我必须再次通过该过程。我真的很感激这方面的一些建议。

谢谢!

注:写在Visual Studio 2005中

回答

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。它与字典基本相同,但是这种结构的价值也是你的关键。你会创建一个像这样的哈希集:

Dim cadParts As New Hashset(Of String) 

我不会通过代码示例,因为它非常接近词典。 ContainsKey变成Contains,Add只接受一个参数(这里是你的零件号)。

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

+1

正是我在想什么。好简洁的解释。 – Demi 2009-05-20 14:09:10

+0

谢谢。我做了一些动作,听起来像你所建议的那样做会更快。但我会诚实的说,我是一个.NET开发者,所以我之前没有使用过字典。你会如此友善地给出一个创建字典函数的代码示例吗? – 2009-05-20 14:41:08

+0

感谢您的代码示例。几个问题 - 1)当你创建字典 - 我的零件号码是字符串。我认为这意味着它应该是“字符串”,对吗? 2)您列为“零件”的第二个参数是期待的类型。我不明白你为什么要把“Part”放在那里。它不应该是字符串?我觉得Part是一个已经假定我创建的对象。 3)我的数组函数只是返回一个列表中的一个零件号码。所以我假设我只是循环它并将其输入到我的字典中,对吗? – 2009-05-20 15:22:05

2

如果零件号是唯一的(它不会在要搜索的值中重复),那么您可以使用已排序的字典。然后删除重复项并使用剩余的项目。

比较您可以用零件号如下:

if(dictionary.ContainsKey(partNumber)) 
    dictionary.Remove(partNumber) 
end if 
2

鉴于只会有一定数量的数据网格中可见的行一次,它可能是更快地实现一些代码OnPaint方法(在这里我有点生疏,因此道歉,如果这不完全正确的话)每一行检查零件信息数组并设置每一行的背景颜色,因为它变得可见,甚至可能标记每一行都经过处理,因此操作不需要重复。在处理所有行时,可能会有一个初始性能增益。

没有实际意义;但是从以前的经验来看,这听起来像是在与AutoDESK Inventor文件进行交互?

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 

希望它可以帮助一点, - 丹