Vb.NET2D字典-非常慢

Vb.NET2D字典-非常慢,vb.net,Vb.net,我需要创建一个2D字典/键值对。 我试过这样的东西 Dim TwoDimData As New Dictionary(Of String, Dictionary(Of String, String)) 'Create an empty table For Each aid In AIDList '(contains 15000 elements) TwoDimData.Add(aid, New Dictionary(Of String, String)) For Each

我需要创建一个2D字典/键值对。 我试过这样的东西

Dim TwoDimData As New Dictionary(Of String, Dictionary(Of String, String))

'Create an empty table
For Each aid In AIDList   '(contains 15000 elements)
    TwoDimData.Add(aid, New Dictionary(Of String, String))
    For Each bid In BIDList   'contains 30 elements
        TwoDimData.Item(aid).Add(bid, "")
    Next
Next

'Later populate values.
[some code here to populate the table]

'Now access the value
'The idea is to access the info as given below (access by row name & col name)
 Msgbox TwoDimData.Item("A004").Item("B005")   ' should give the value of 2
 Msgbox TwoDimData.Item("A008").Item("B002")   ' should return empty string. No error

问题:


问题在于创建空表。创建带有空值的TwoDimData表需要70秒。其他一切似乎都很好。是否有任何方法可以提高性能-可以代替使用字典

我建议您尝试使用
字典(元组的,字符串的,字符串的)
。也就是说,键是字符串对(
Tuple(of String,String)
),值是字符串。这看起来与你问题中的图表很吻合

Dim matrix As New Dictionary(Of Tuple(Of String, String), String)

' Add a value to the matrix:
matrix.Add(Tuple.Create("A003", "B004"), "3")

' Retrieve a value from the matrix:
Dim valueAtA003B004 = matrix(Tuple.Create("A003", "B004"))
当然,您可以定义自己的键类型(表示两个字符串的组合),如果它对您的口味来说过于通用

或者,您也可以只使用(可能)二维数组,但如果您的数据是(即,如果该二维矩阵中有许多空单元格),则可能会浪费大量空间;你将被迫使用数字索引而不是字符串

<强> P.S:实际上,考虑将字典值类型从<代码>字符串< /代码>更改为<代码>整数< /代码>;您的示例矩阵表明它只包含整数,因此将它们存储为字符串可能没有意义

p.p.S.:不要将“空”单元格的值添加到字典中。那将是非常浪费的。相反,不是简单地从字典中检索值,而是检查字典是否包含键:

Dim valueA As String = ""  ' the default value
If matrix.TryGetValue(Tuple.Create("A007", "B002"), valueA) Then
    ' the given key was present, and the associated value has been retrieved
    …
End If

我认为一个简单的结构就足够了

Public Structure My2DItem
  Public Row As Integer
  Public Col As Integer
  Public Value As String
End Structure

Public My2DArray As Generic.List(Of My2DItem) = Nothing
Public Size As Integer
Public MaxRows As Integer
Public MaxCols As Integer
'
Sub Initialise2DArray()
'
Dim CountX As Integer
Dim CountY As Integer
Dim Item As My2DItem
'
  'initialise
  MaxRows = 15000
  MaxCols = 30
  Size = MaxRows * MaxCols
  My2DArray = New Generic.List(Of My2DItem)
  '   
  'Create an empty table
  For CountY = 1 To 15000
    For CountX = 1 To 30
      Item = New My2DItem
      Item.Row = CountY
      Item.Col = CountX
      Item.Value = "0"
      My2DArray.Add(Item)
      Item = Nothing
    Next
  Next
'
End Sub
要从数组中读取数据

Function GetValue(Y As Integer, X As Integer) As String
'
Dim counter As Integer
'
GetValue = "Error!"
If My2DArray.Count > 0 Then
  For counter = 0 To My2DArray.Count - 1
    If My2DArray(counter).Row = Y Then
      If My2DArray(counter).Col = X Then
        GetValue = My2DArray(counter).Value
        Exit Function
      End If
    End If
  Next
End If
'
End Function
并读取样本单元格A004 B005

MyStringValue = GetValue(4,5)

我建议创建一个具有AID和BID属性的类,并将其用作要存储的值的基础

Public Class AIdBId
    Public Property AId As Integer
    Public Property BId As Integer
    Public Sub New(aId As Integer, bId As Integer)
        Me.AId = aid
        Me.BId = bid
    End Sub
End Class
请注意,我对所有内容都使用了整数,因为这似乎是您所需要的,而且使用字符串更有效

然后可以在非零值处添加值:

'define your dictionary
Dim valueMatrix As New Dictionary(Of AIdBId, Integer)

'add your values
valueMatrix.Add(New AIdBId(1, 1), 1)
valueMatrix.Add(New AIdBId(2, 3), 1)
valueMatrix.Add(New AIdBId(4, 3), 3)
valueMatrix.Add(New AIdBId(5, 8), 8)

'check if a value exixts
Dim valueExixsts As Boolean = valueMatrix.ContainsKey(New AIdBId(9, 9))

'get a value
Dim i As Integer = valueMatrix(New AIdBId(4, 3))
因此,如果存在一个值,您现在可以将这两个值组合起来返回该值,如果没有,则返回零:

 Private Function GetValue(valuematrix As Dictionary(Of AIdBId, Integer), aId As Integer, bId As Integer) As Integer
    Dim xRef As New AIdBId(aId, bId)
    If valuematrix.ContainsKey(xRef) Then
        Return valuematrix(xRef)
    Else
        Return 0
    End If
End Function

现在使用Tuple需要69秒,这是我提出的一个愚蠢的问题。谢谢你抽出时间。加上1.69秒(而不是70秒)并没有多大的改进…?我需要空值来满足我的需求,因为我需要创建一个类似于表的矩阵。当我使用字典(错误的逻辑)时,性能在68-71秒之间。元组连续69秒(逻辑相同错误)。我看不到Tuple有任何性能改进。但是你有没有尝试过字典和元组?无论如何,谢谢你的时间。这里发生了一些奇怪的事情。我运行了你的代码,代码占用了我的计算机大约85毫秒。您的代码运行速度慢了823倍。你还干什么?@Enigmativity,你是怎么尝试的?你能告诉我你是怎么做的吗。对我来说,其他一切都很好。除了创建一个空表需要超过68秒之外。不太清楚发生了什么。看看这段代码——它在LINQPad中运行大约85毫秒。它不会在dotnetfiddle上运行,因为它使用了太多的内存。哦,伙计……你的例子帮助我纠正了这个问题。你太棒了。作为回报,我会投票给你一些答案:)这有什么帮助?这基本上和你在问题中的代码一样。这是我提出的一个愚蠢的问题。谢谢你抽出时间。加1