【问题标题】:vb.net - Inserting 1-dimensional arrays into a 2-dimensional arrayvb.net - 将一维数组插入二维数组
【发布时间】:2013-07-30 11:27:12
【问题描述】:

我正在研究一种优化算法,需要将一些数据(由算法生成)存储在一个名为 matrix 的二维数组中,其中 row(i) 包含优化的适应度得分和参数值向量(一)。

Dim matrix(vectorCount() - 1, parameterCount()) As Double
Dim params(parameterCount() - 1) As Double

For i As Integer = 0 To vectorCount() - 1
    matrix(i, 0) = vectorScore(i)
    params = vectorValues(i)
    For j As Integer = 0 To params.Length - 1
        matrix(i, j+1) = params(j)
    Next
Next

int vectorCount() 返回向量的数量。
int parameterCount() 返回每​​个向量中的参数个数。
double vectorScore(int vectorIndex) 返回指定向量的适应度得分。
double[] vectorValues(int vectorIndex) 返回指定向量的参数值。

我的问题:
是否有更快(即更有效)的方法将params 插入matrix

【问题讨论】:

    标签: vb.net multidimensional-array insertion


    【解决方案1】:

    如果你想要效率,依赖“普通”数组无疑是最好的选择。它们相对于其他替代方案(集合、列表等)如此高效的原因是它们包含所需的最少信息量。如果您想要能够轻松/快速地对信息进行排序或编写复杂查询来检索数据的花哨功能,则不应依赖数组。

    我总是依赖于您编写的代码,并且从未遇到过速度问题(这真的很快)。我做了一个快速的研究,以确保没有其他选择,但找不到任何选择。您拥有的最接近的东西是Array.Copy,尽管它仅在数组具有相同维度时才有效(我个人仅将它与一维数组一起使用)。无论如何,我发现了一个interesting link,关于 Array.Copy() 与 2D 数组的循环性能(它在 C# 中,但一切都适用于 VB.NET)。

    总结:您的代码非常快,不需要改进。如果有一个有效的替代方案(Array.Copy 适用于 2D 和 1D,不存在的),结果性能会好一点(并且仅适用于小数组大小)。

    【讨论】:

    • +1 好答案!在我的例子中,循环 `ìcould easily have up to 10-20 million iterations and loop j` 最多 12-15 次迭代,总共至少 1.2 亿次迭代。即使有这些数字,我的代码也是一个不错的选择吗?
    • @bluebox 谢谢。我想你的答案也值得知道(人们最近也担心简单的编码和低效的存储替代方案)-> 立即 +1。
    • @bluebox 实际上使用这些数字,您的代码是唯一可接受的解决方案(即使在拥有工作 Array.Copy 的不切实际的情况下)。正如您在提供的链接中所见,数组大小越大(= 迭代次数越多),循环性能就越好。
    • @bluebox 我猜你知道创建太大的数组不是一个好主意(根本);所以我知道您正在考虑不同的数组或在不同的时刻执行迭代,但您并没有将所有这些记录放在同一个数组中。
    • @bluebox 没问题。尝试尽可能多地使用一维数组,当移动到二维时,打算将第一维保持在 1000 以下。这取决于数组的数量和给定计算机的内存;这是最安全的建议。您是必须进行性能测试并在预期条件下得出实际限制的人。但这是一个完全不同的故事。我对您的问题的回答很明确:这是最好的方法吗?是的。 :)
    【解决方案2】:

    如果要使用多个线程,可以使用并行for循环。

    http://msdn.microsoft.com/en-us/library/dd460713.aspx

    Dim matrix(vectorCount() - 1, parameterCount()) As Double
    Dim params(parameterCount() - 1) As Double
    
    Parallel.For(0, vectorCount() - 1, Sub(i)
                                          matrix(i, 0) = vectorScore(i)
                                          params = vectorValues(i)
                                          For j As Integer = 0 To params.Length - 1
                                              matrix(i, j+1) = params(j)
                                          Next
                                       End Sub)
    

    【讨论】:

      【解决方案3】:

      这在很大程度上取决于数组的大小,for 循环非常有效,但是对于非常大的数组,您可以看到使用 array.copy 或 buffer.blockcopy 的改进。

      Sub Main()
      
          Const ARR_SIZE_X As Integer = 9999999
          Const ARR_SIZE_y As Integer = 5
          Const DBL_SIZE As Integer = 8
      
          Dim watch As New Stopwatch
      
          Dim a1(ARR_SIZE_X) As Double
          Dim a2(ARR_SIZE_y, ARR_SIZE_X) As Double
      
          For x = 0 To ARR_SIZE_X
              a1(ARR_SIZE_X) = x
          Next
      
          watch.Start()
      
          For t = 0 To 10
              For y = 0 To ARR_SIZE_y
                  For x = 0 To ARR_SIZE_X
                      a2(y, x) = a1(x)
                  Next
              Next
          Next
      
          watch.Stop()
          Console.WriteLine(watch.ElapsedTicks)
      
          watch.Reset()
      
          watch.Start()
      
          For t = 0 To 10
              For y = 0 To ARR_SIZE_y
                  System.Buffer.BlockCopy(a1, 0, a2, (ARR_SIZE_X + 1) * DBL_SIZE * y, DBL_SIZE * ARR_SIZE_X)
              Next
          Next
      
          watch.Stop()
          Console.WriteLine(watch.ElapsedTicks)
      
          'For y = 0 To 4
          '    For x = 0 To 4
          '        Console.Write(a2(y, x))
          '    Next
      
          '    Console.WriteLine()
          'Next
      
          Console.ReadLine()
      
      End Sub
      

      【讨论】:

        【解决方案4】:
        Function OneD2TwoD(ByVal xLen As Integer, ByVal yLen As Integer)
            ' (1) populate 1d array
            Dim TwoD(xLen, yLen) As Integer
            Dim OneD((xLen + 1) * (yLen + 1) - 1) As Integer
            For i As Integer = 0 To OneD.GetUpperBound(0)
                OneD(i) = i
            Next
            PrintValues(OneD, "|")
            Console.WriteLine()
            ' (2) Convert 1d array to 2d array/
            Dim z, Row(yLen) As Integer
            For x As Integer = 0 To xLen
                For y As Integer = 0 To yLen
                    z = x * (yLen + 1) + y
                    TwoD(x, y) = OneD(z)
                    Row(y) = TwoD(x, y)
                Next
                PrintValues(Row, "|")
            Next
            Console.WriteLine()
            ' (3) Convert 2d array to 1d array/
            Erase OneD
            ReDim OneD((xLen + 1) * (yLen + 1) - 1)
            For x As Integer = 0 To xLen
                For y As Integer = 0 To yLen
                    z = y + x * (yLen + 1)
                    OneD(z) = TwoD(x, y)
                Next
            Next
            PrintValues(OneD, "|")
        End Function
        
        Public Sub PrintValues(ByVal myList As IEnumerable, ByVal mySeparator As Char)
            ' source: https://msdn.microsoft.com/en-us/library/system.collections.arraylist.add(v=vs.110).aspx
            Dim obj As [Object]
            For Each obj In myList
                Console.Write("{0}{1}", mySeparator, obj)
            Next obj
            Console.WriteLine()
        End Sub 'PrintValues
        

        示例:OneD2TwoD(0, 10)

        (1) 填充一维数组

        |0|1|2|3|4|5|6|7|8|9|10

        (2) 将一维数组转换为二维数组

        |0|1|2|3|4|5|6|7|8|9|10

        (3) 将二维数组转换为一维数组

        |0|1|2|3|4|5|6|7|8|9|10

        示例:OneD2TwoD(5, 0)

        (1) 填充一维数组

        |0|1|2|3|4|5

        (2) 将一维数组转换为二维数组

        |0

        |1

        |2

        |3

        |4

        |5

        (3) 将二维数组转换为一维数组

        |0|1|2|3|4|5

        示例:OneD2TwoD(2, 5)

        (1) 填充一维数组

        |0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17

        (2) 将一维数组转换为二维数组

        | 0| 1| 2| 3| 4| 5

        | 6| 7| 8| 9|10|11

        |12|13|14|15|16|17

        (3) 将二维数组转换为一维数组

        |0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17

        感谢您的关注

        【讨论】:

        • 请尽量避免仅仅将代码作为答案,并尝试解释它的作用和原因。对于没有相关编码经验的人来说,您的代码可能并不明显。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-02-06
        • 1970-01-01
        • 1970-01-01
        • 2017-01-03
        • 1970-01-01
        • 1970-01-01
        • 2021-03-18
        相关资源
        最近更新 更多