【问题标题】:3 nested loops in an array - VBA数组中的 3 个嵌套循环 - VBA
【发布时间】:2026-02-19 15:40:01
【问题描述】:

我在一个数组中有 2 个嵌套循环,但据我所知,我需要第三个,但我无法实现。

我有以下数据(黄色):

当前代码按实际行为列中的指示计算:

Dim arr, outarr as Variant
Dim lastc, lastr as long

lastc = 2
lastr = Cells(ws.Rows.count, lastc).End(xlUp).Row
    arr = Range(Cells(2, lastc), Cells(lastr, lastc))
      cnt = ((UBound(arr, 1) - 1) * UBound(arr, 1)) / 2
          k = 1
            ReDim outarr(1 To cnt, 1 To 1)
                For i = LBound(arr, 1) + 1 To UBound(arr, 1)
                       For j = LBound(arr, 1) To i - 1
                             outarr(k, 1) = arr(j, 1) - arr(i, 1)
                                
        k = k + 1
                        Next j
              Next i

期望的行为是从 1.1 到 6.1 的值将最小值存储在该范围内作为结果。 10 - 0 = 10 但我需要该范围内的实际最小值(1.6 到 6.6),最小值为 10 - 40 = -30。

始终将最小值计算为范围的第一个值 - 范围的 X 值非常重要。给定循环中的第一个值是一个常数。

我认为需要第三个循环来存储最小值,然后将此值插入到 outarr,但我还没有成功。

感谢您的帮助。

【问题讨论】:

  • 我不确定我是否正确理解了最小值部分。对于B7-B3,最小值不是5 - 40吗?和B7-B2,最小值为0 - 40?
  • @RaymondWu 更新了我的查询。感谢您指出了这一点。范围内的第一个值是一个常数,计算基于(第一个值 - X 值,第一个值 - Y 值.....)。
  • 抱歉,我还是没听懂,对于B5-B3,输出是25但不是最小值30 - 40
  • @RaymondWu 是的,你是对的。我只是没有计算那个,因为在 B7 示例中解释了所需的行为。但是,是的,最小值是 - 10。
  • @RaymondWu 还有一个问题 Raymond。这个循环是更大循环的一部分,当我尝试访问下一个循环时,输出索引增加了 1。知道为什么吗?行数,数组大小,一切都是一样的。谢谢。

标签: arrays excel vba loops


【解决方案1】:

我没有创建另一个循环,而是记录每个循环中的最小值并与内部循环中的新值进行比较:

Option Explicit

Private Sub Test()
    Const startRow As Long = 2
    Const valueCol As Long = 2
    Const outputCol As Long = 4
    
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Worksheets("Sheet1")
        
    Dim lastRow As Long
    lastRow = ws.Cells(ws.Rows.Count, valueCol).End(xlUp).Row
    
    Dim inputArr As Variant
    inputArr = ws.Range(ws.Cells(startRow, valueCol), ws.Cells(lastRow, valueCol)).Value
    
    Dim outputSize As Long
    outputSize = ((UBound(inputArr, 1) - 1) * UBound(inputArr, 1)) / 2
    
    Dim outputIndex As Long
    Dim outputArr As Variant
    ReDim outputArr(1 To outputSize, 1 To 1) As Variant
    
    Dim i As Long
    Dim n As Long
    
    Dim currFirst As Long
    Dim currLowest As Long
    
    For i = 2 To UBound(inputArr, 1)
        currFirst = inputArr(i, 1)
        currLowest = currFirst - inputArr(i - 1, 1)
                
        For n = i - 1 To 1 Step -1
            Dim testLowest As Long
            testLowest = currFirst - inputArr(n, 1)
            
            If testLowest < currLowest Then currLowest = testLowest
            
            outputIndex = outputIndex + 1
            outputArr(outputIndex, 1) = currLowest
        Next n
    Next i
    
    ws.Cells(startRow, outputCol).Resize(UBound(outputArr, 1)).Value = outputArr
End Sub

【讨论】:

  • 谢谢雷蒙德。不得不修改代码的某些部分以满足我的需要,但效果很好。
【解决方案2】:

我相信这会产生预期的结果。

我在第一级中添加了一个额外的辅助循环,而不是添加第三个嵌套循环。

请注意: 这应该让您知道如何以比另一层 For Next 循环更小的复杂性来处理这个问题,但是由于定位,性能会随着迭代的增长而下降.

我已将一些变量重命名为更具描述性(x 除外,因为我很懒惰)。

解释在代码下方,这里是重新设计的循环部分。

OutputCounter = 1
For LayerOneStep = LBound(ValueArray, 1) To UBound(ValueArray, 1)
    ReDim TempArray(1 To LayerOneStep)
    For x = 1 To UBound(TempArray)
        TempArray(x) = ValueArray(x, 1)
    Next x
    For LayerTwoStep = LBound(ValueArray, 1) To LayerOneStep - 1
        MaxValue = WorksheetFunction.Max(TempArray)
        TempValue = (ValueArray(LayerOneStep, 1) - ValueArray(LayerTwoStep, 1))
        If ValueArray(LayerOneStep, 1) = 0 Or ValueArray(LayerTwoStep, 1) = 0 Then
            OutputArray(OutputCounter) = TempValue
            OutputCounter = OutputCounter + 1
        ElseIf TempValue < ValueArray(LayerOneStep, 1) - MaxValue Then
            OutputArray(OutputCounter) = TempValue
            OutputCounter = OutputCounter + 1
        Else
            OutputArray(OutputCounter) = ValueArray(LayerOneStep, 1) - MaxValue
            OutputCounter = OutputCounter + 1
        End If
    Next LayerTwoStep
Next LayerOneStep
  • TempArray() 用于存储您的分组值。 IE。 B3 & B2B5 & B4 & B3 & B2 等。这是通过将 B 列第 2 行的值分配给 LayerOne 计数器的值来实现的到行。这些值是从现有的 ValueArray 数组中分配的,而不是每次都再次访问工作表。
  • 以这种方式分配它允许我们使用WorksheetFunction.Max() 函数来查找集合中的最大数。 (请记住,如上所述,不是最基于性能的方式)
  • 然后我们使用一些变量来分配一些计算。上面的 MaxValueTempValue 是 x-y 方法 - 结果与工作表公式相同。
  • 然后我们使用一些If...Then...Else 逻辑来开始计算基于计算范围的绝对最小值。
  • 拳头If 条件正在检查作为TempValue 计算一部分的任一值是否为零(0)。如果是,它会返回一些时髦的结果,这样可以确保我们将 x - 0 或 0 - y 结果传递给OutputArray
  • 其次是检查TempValue 计算的计算结果是否小于 x - MaxValue。如果是,它会将TempValue 返回到OutputArray
  • 否则,我们将 x - MaxValue 返回到 OutputArray

以上代码的结果;

【讨论】: