0

我有一个用 VB.net 编写的函数,代码如下所示。

For rowIndex As Integer = 0 To nRows - 1
        Dim max As Integer = -1
        Dim arrTemp() As String
        arrTemp = Nothing

        For columnIndex As Integer = 0 To nCols - 1
            If IsNumeric(arrTranspose(rowIndex, columnIndex)) Then
                Dim iVal As Integer = arrTranspose(rowIndex, columnIndex)

                If iVal < 0 Then
                    iVal = Math.Abs(iVal)
                End If

                If max < iVal Then
                    max = iVal
                    ReDim Preserve arrTemp(max)
                End If
                arrTemp(iVal) += String.Format("{0},", (columnIndex + 1))
            End If
        Next
        arrRespondentIDs(rowIndex) = arrTemp
    Next

nRow = 210 nCols = 64772

在上面的代码中,第一次循环执行需要 4 到 5 分钟,我进行了研究并观察到,然后由于 IsNumeric 函数需要更多时间,对此不确定。

任何人都可以知道代码的哪一部分导致性能问题。请分享你的想法。

谢谢,穆罕默德萨迪克。

4

1 回答 1

2

您编写的代码复杂度为 O(n^2),无法很好地扩展。从外观上看,您对此无能为力。改进内循环内部代码的具体方法:

  • 您使用 IsNumeric() 这是一个非常昂贵的函数,因为它处理很多极端情况。就像表示货币金额的值一样,可能包括负数的括号或像 $ 或“USD”这样的单位。但您实际上只对可以转换为Integer的值感兴趣,接下来您要做的事情是 IsNumeric() 函数不会告诉您这一点。当然,这样的货币金额不会很好地转换。所以使用更准确的转换函数,也更快,比如 Integer.TryParse()。

  • 测试If iVal < 0 Then毫无意义,Math.Abs​​() 函数已经做到了。直接调用就行了。

  • ReDim Preserve arrTemp(max) 非常昂贵,令人惊讶的是它没有在您的个人资料会话中弹出。您将一遍又一遍地重新分配和复制数组。你真的应该使用 List(Of String) 而不是数组。它特别擅长最大限度地减少这种费用。

  • 这个arrTemp(iVal) += String.Format("{0},", (columnIndex + 1))声明代价高昂,而且犯下了让你一开始就陷入这种麻烦的同一种罪。将数据存储为字符串是非常不明智的,它是一种非常笨拙的数据格式,永远需要转换回来,消耗 CPU 周期没有任何好处。当人们查看数据时,您只关心字符串,这只发生在代码中的不同位置。如果数据以二进制格式保存,则程序运行效率最高。这里没有歧义,columnIndex 始终是一个整数。结合上一个项目符号,arrTemp 不应该是一个字符串数组,而是一个 List(Of Integer)。

通过在代码的其余部分中去掉 String 作为数据类型,找到改进此代码的其他方法。甚至 Object 也比 String 好。

于 2012-08-11T14:27:48.370 回答