操作没有循环的数组

学习Excel的VBA,我正在尝试尽可能多的编码,而不使用循环。 作为一个练习,乘以两个相邻的范围的数字,我想出了这个:

Sub multiply_range() Dim a, b, c As Range Set a = Range("a1:a5") Set b = Range("b1:b5") Set c = Range("c1:c5") a.Value = Evaluate("row(" & a.Address & ")") b.Value = Evaluate("row(" & b.Address & ")") c.Value = Evaluate(a.Address & "*" & b.Address) End Sub 

哪个工作很好。 现在我想做类似的事情,但使用数组。 从这个代码开始:

 Sub multiply_array() Dim aArr(), bArr(), cArr() ReDim aArr(5), bArr(5), cArr(5) For i = 0 To 4 aArr(i) = i + 1 bArr(i) = i + 1 Next For i = 0 To 4 cArr(i) = aArr(i) * bArr(i) Next For i = 0 To 4 Range("D" & i + 1).Value = cArr(i) Next End Sub 

你将如何用不使用循环的代码replace这些FOR循环中的任何一个?

干得好:

 Sub Squares() Dim n& n = 5 [d1].Resize(n) = Evaluate("row(1:" & n & ")^2") End Sub 

UPDATE

这是一个不使用循环且不使用范围的变体:

 Sub Squares() Dim a, b, n& n = 5 a = Array(1, 2, 3, 4, 5) b = Array(1, 2, 3, 4, 5) [d1].Resize(n) = Evaluate("{" & Join(a, ";") & "}*{" & Join(b, ";") & "}") End Sub 

对于任意数组的乘法,你可以尝试把这个代码粘贴到一个新的模块中:

 Dim X, Y Sub MultiplyArrays() Dim Z X = Array(1, 2, 3, 4, 5) Y = Array(1, 2, 3, 4, 5) Z = [GetX()*GetY()] Range("D1").Resize(UBound(Z)) = Application.Transpose(Z) End Sub Function GetX() GetX = X End Function Function GetY() GetY = Y End Function 

另一个稍微棘手的方法是使用工作表函数方法:

 Sub MultiplyArrays2() Dim X, Y, Z X = Array(1, 2, 3, 4, 5) Y = Array(1, 2, 3, 4, 5) With Application Z = .PV(, 1, .PV(, X, Y)) Range("D1").Resize(UBound(Z)) = .Transpose(Z) End With End Sub 

另请参阅: 在VBA中添加或乘上变体

您可以创build一些辅助函数,这些辅助函数受函数式编程的启发。 您可以将它们存储在一个模块中(与其他用于处理数组的函数一起)并根据需要导入它们。

 Function Map(f As String, A As Variant) As Variant 'assumes that A is a 1-dimensional variant array 'and f is the name of a function that can be applied to it Dim i As Long Dim M As Variant ReDim M(LBound(A) To UBound(A)) For i = LBound(A) To UBound(A) M(i) = Application.Run(f, A(i)) Next i Map = M End Function Function ZipWith(f As String, A As Variant, B As Variant) 'assumes that A,B are 1-dimensional variant arrays with the same bounds 'and f is the name of a function with two variables Dim i As Long Dim M As Variant ReDim M(LBound(A) To UBound(A)) For i = LBound(A) To UBound(A) Select Case f: Case "+": M(i) = A(i) + B(i) Case "-": M(i) = A(i) - B(i) Case "*": M(i) = A(i) * B(i) Case "/": M(i) = A(i) / B(i) Case "&": M(i) = A(i) & B(i) Case "^": M(i) = A(i) ^ B(i) Case Else: M(i) = Application.Run(f, A(i), B(i)) End Select Next i ZipWith = M End Function 

像这样testing:

 Function square(x As Variant) As Variant square = x * x End Function Sub test() Dim A As Variant, B As Variant, squares As Variant, products As Variant A = Array(2, 3, 4) B = Array(5, 6, 7) squares = Map("square", A) products = ZipWith("*", A, B) Debug.Print Join(squares, " ") Debug.Print Join(products, " ") End Sub 

注意testing子中没有循环。 产出如预期:

 4 9 16 10 18 28