【问题标题】:Array's cumulative sum数组累计和
【发布时间】:2018-03-02 19:09:33
【问题描述】:

我有一个整数数组,想找到一种简单的方法来计算其累积和 (S = Data(1) + Data(2) + ... + Data(x))。

我已经创建了这个函数:

Function CumulativeSum(Data() As Integer, k As Integer) As Integer
    For entry = 1 To k
        CumulativeSum = CumulativeSum + Data(entry)
    Next entry
End Function

它工作正常。但是,我想知道是否有更好的方法(主要是不使用任何额外的函数,基本上只使用像Application.Sum 这样的excel函数)。我在网上做了一个小搜索,但在此基础上没有找到任何东西。

我知道我不是要求更正任何代码,我只是要求一个替代方案,这不是本论坛的真正目的。但是,我也怀疑答案可能很简单,所以......如果有人愿意帮助我,我会非常非常感激!如果您找到类似问题的答案,请与我分享链接,我将删除此链接。

我很抱歉可能没有明确地满足我的要求:我只是想找到一种简单的方法来使用宏例程本身的简单函数来计算累积总和,而不使用我创建的 CumulativeSum 函数或用户创建的任何其他功能。

【问题讨论】:

  • 为什么不添加一个简单的包含 4 个数字的示例数组以及您想要实现的目标?
  • @MacroMarc,感谢您的建议。这可能有助于更快地得到一个好的答案。但是你已经给了我我想要的答案!
  • @Pspl,您的示例和来自@MacroMarc 的解决方案没有计算累积和。它只是计算给定数组上从索引 1 到 i 的常规总和。您也可以将其称为子集的总和或部分总和。例如,在您的示例中,您必须将CumulativeSum = CumulativeSum + Data(entry) 更改为CumulativeSum = CumulativeSum + Data(entry) * (k - entry + 1) 才能计算到索引k 的累积总和。所以请更新您的问题。

标签: arrays vba excel cumulative-sum


【解决方案1】:

如果你想从 Array(a,b,c) 中实现一个像 Array(a,a+b,a+b+c) 这样的累积数组,那么这个函数就是实现它,如果你想传递开始和结束参数:

Public Sub TestMe()

    Dim outputArray     As Variant
    Dim inputArray      As Variant
    Dim counter         As Long

    inputArray = Array(1, 2, 4, 8, 16, 32, 64)

    outputArray = generateCumulativeArray(inputArray, 1, 4)
    For counter = LBound(outputArray) To UBound(outputArray)
        Debug.Print outputArray(counter)
    Next counter

    outputArray = generateCumulativeArray(inputArray, toValue:=4)
    For counter = LBound(outputArray) To UBound(outputArray)
        Debug.Print outputArray(counter)
    Next counter

End Sub

Public Function generateCumulativeArray(dataInput As Variant, _
                                        Optional fromValue As Long = 0, _
                                        Optional toValue As Long = 0) As Variant

    Dim i                   As Long
    Dim dataReturn          As Variant
    ReDim dataReturn(0)
    dataReturn(0) = dataInput(fromValue)

    For i = 1 To toValue - fromValue
        ReDim Preserve dataReturn(i)
        dataReturn(i) = dataReturn(i - 1) + dataInput(fromValue + i)
    Next i
    generateCumulativeArray = dataReturn
End Function

关于只是对数组求和,这样做的方法是: 您可以使用 WorksheetFunction. 并且可以将数组作为参数传递。因此,您可以获得所有功能,例如AverageMinMax 等:

Option Explicit

Public Sub TestMe()

    Dim k As Variant
    k = Array(2, 10, 200)
    Debug.Print WorksheetFunction.Sum(k)
    Debug.Print WorksheetFunction.Average(k)

End Sub

如果您想要从给定开始到给定结束的总和,最简单的方法可能是创建一个新数组并将其完全求和。在 Python 中这称为切片,在 VBA 中可以手动完成:

Public Sub TestMe()

    Dim varArr          As Variant
    Dim colSample       As New Collection

    varArr = Array(1, 2, 4, 8, 16, 32, 64)

    colSample.Add (1)
    colSample.Add (2)
    colSample.Add (4)
    colSample.Add (8)

    Debug.Print WorksheetFunction.Sum(generateArray(varArr, 2, 4))
    Debug.Print WorksheetFunction.Sum(generateArray(colSample, 2, 4))

End Sub

Public Function generateArray(data As Variant, _
                              fromValue As Long, _
                              toValue As Long) As Variant

    Dim i                   As Long
    Dim dataInternal        As Variant
    Dim size                As Long

    size = toValue - fromValue
    ReDim dataInternal(size)

    For i = LBound(dataInternal) To UBound(dataInternal)
        dataInternal(i) = data(i + fromValue)
    Next i

    generateArray = dataInternal

End Function

这个想法是generateArray 函数返回一个新数组。因此,它的完整总和就是您所需要的。它也适用于集合,不仅适用于数组。请注意,使用集合时,它们从索引 1 开始,而数组(通常)从 0 开始。如果您想对数组和集合使用相同的索引,请将 generateArray 函数更改为这个:

Public Function generateArray(data As Variant, _
                              fromValue As Long, _
                              toValue As Long) As Variant

    Dim i                   As Long
    Dim dataInternal        As Variant
    Dim size                As Long

    size = toValue - fromValue
    ReDim dataInternal(size)

    If IsArray(data) Then
        For i = LBound(dataInternal) To UBound(dataInternal)
            dataInternal(i) = data(i + fromValue)
        Next i
    Else
        For i = LBound(dataInternal) To UBound(dataInternal)
            dataInternal(i) = data(i + fromValue + 1)
        Next i
    End If

    generateArray = dataInternal

End Function

或者在顶部写Option Base 1,数组将从1开始(不建议!)。

【讨论】:

  • 对于输入 [a, b, c],累积总和应返回 a + a+b + a+b+c。除非弄错了,否则您的答案并不能解决问题,因为将数组切片以将其与 WorksheetFunction.Sum 求和将计算常规总和而不是累积总和。
  • @FlorentB。 - 谢谢,我刚刚编辑过,包括这些信息。
  • @FlorentB。 OP的函数也不返回累积和,他/她说预期的结果应该是= Data(1) + Data(2) + ... + Data(x),所以我猜测需要的实际上是一个常规的和,而不是累积总和尽管 OP 在标题、问题和标签中包含 cumulative sum
  • @AhmedAbdelhameed - 是的! :)
  • @AhmedAbdelhameed 我的CumulativeSum 函数返回一个累积和......至少在我的机器上! CumulativeSum(Data, 3) = Data(1) + Data(2) + Data(3)。你试过了吗??
【解决方案2】:

试试这个:

Sub test()
Dim arr As Variant
arr = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

Dim mySum As Long, k As Long
Dim wsf As WorksheetFunction
Set wsf = Application.WorksheetFunction

k = 6
'operative line below
mySum = wsf.Sum(wsf.Index(arr, 1, Evaluate("ROW(1:" & k & ")")))

MsgBox mySum

End Sub

【讨论】:

  • 正是我要找的......一种仅使用简单的excel函数获取累积和的方法!非常感谢!!
【解决方案3】:

对于累积总和,请尝试以下操作

Function CumulativeSum(Data() As Integer, k As Integer) As Integer
    Dim tempArr
    tempArr = Data
    ReDim Preserve temp(0 To k - 1)
    CumulativeSum = WorksheetFunction.Sum(tempArr)
End Function

编辑:

Sub Demo()
    Dim MyArray
    Dim i As Long
    MyArray = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)

    Debug.Print MyArray(LBound(MyArray))
    For i = LBound(MyArray) + 1 To UBound(MyArray)
        MyArray(i) = MyArray(i - 1) + MyArray(i)
        Debug.Print MyArray(i)
    Next i
End Sub

以上代码更新数组arr from
1, 2, 3, 4, 5, 6, 7, 8, 9

1, 3, 6, 10, 15, 21, 28, 36, 45

【讨论】:

  • 我的功能不用调整了。我的工作正常。我想要的是确定一种在没有功能的情况下以简单的方式做同样事情的方法。对不起。
  • @Pspl - 如果我没记错的话,你正在传递一个带有 k (比如 5)的数组(比如 10 项),那么你应该能够对传递的数组的前 5 项求和。
  • @Pspl - 如果这是正确的,那么与您的函数相比,这就是我的函数以简单的方式所做的事情。
  • 是的。你没有错!但是像 sum(array, ...) 这样带有某种参数的函数会更好......这就是我正在寻找的......
  • @Pspl - 查看更新的代码。此代码将数组MyArray10,20,30,40,50 转换为10,30,60,100,150
【解决方案4】:

此函数返回一个数组,其中包含原始向量的累积和。

Function CumuVector(Vec As Variant) As Variant()
Dim element, v() As Variant
Dim i As Integer
lastindexinvec = 0
For Each element In Vec
    lastindexinvec = last + 1
Next 
ReDim v(lastindexinvec) As Variant
i = 0
For Each element In Vec
    If i < last Then
    sum = sum + element
    v(i) = sum
    i = i + 1
    End If
Next
CumuVector = v
End Function

【讨论】:

    猜你喜欢
    • 2019-05-14
    • 2014-08-11
    • 1970-01-01
    • 2023-02-25
    • 1970-01-01
    • 1970-01-01
    • 2013-05-26
    • 2013-08-01
    相关资源
    最近更新 更多