如何反转一个充满整数的数组,例如:
[1;5;8;45;54]
要:
[54;45;8;5;1]
我可以使用任何内置功能吗?
我尝试使用this方法:
Array.Reverse(arr)
我在Tools>中添加了Mscorlib.dll引用,但它显示错误:语法错误。在Array.Reverse(arr)位置。
答案 0 :(得分:9)
您可以使用ArrayList
类并包装其Reverse
方法:
Function ReverseArray(arr As Variant) As Variant
Dim val As Variant
With CreateObject("System.Collections.ArrayList") '<-- create a "temporary" array list with late binding
For Each val In arr '<--| fill arraylist
.Add val
Next val
.Reverse '<--| reverse it
ReverseArray = .Toarray '<--| write it into an array
End With
End Function
用作:
Sub main()
Dim arr As Variant
arr = ReverseArray(Array(1, 2, 3, 4, 5)) '<-- it returns an array of Variant/Integer with values 5,4,3,2,1
End Sub
答案 1 :(得分:4)
Array.Reverse
听起来像VB.Net,而不是VBA。
Chip Pearson可以为你想要对阵列(和其他结构)做任何事情提供任何功能。
http://www.cpearson.com/excel/vbaarrays.htm - &gt; ReverseArrayInPlace
相关部分是:
Ndx2 = UBound(InputArray)
' loop from the LBound of InputArray to the midpoint of InputArray
For Ndx = LBound(InputArray) To ((UBound(InputArray) - LBound(InputArray) + 1) \ 2)
'swap the elements
Temp = InputArray(Ndx)
InputArray(Ndx) = InputArray(Ndx2)
InputArray(Ndx2) = Temp
' decrement the upper index
Ndx2 = Ndx2 - 1
Next Ndx
答案 2 :(得分:1)
Andre的答案指的是Chip Pearson的函数我认为for循环中的+1是错误的,在LBound和UBound的情况下,不是偶然或者两者都是ODD导致中点逆转被恢复。即LBound和UBound之间的差异是ODD。
考虑0 = LBound和9 = UBound。
9 + 1 = 10/2 = 5
因此循环将用于Ndx = 0到5.这是6次迭代。一次迭代太多了。
以下互换结果。
Ndx = 0,Ndx2 = 9:0&lt;&gt; 9
Ndx = 1,Ndx2 = 8:1&lt;&gt; 8
Ndx = 2,Ndx2 = 7:2&lt; 7&gt;
Ndx = 3,Ndx2 = 6:3&lt; 6&gt;
Ndx = 4,Ndx2 = 5:4&lt; 5&gt; 5
Ndx = 5,Ndx2 = 4:5&lt; 4&gt;
所以中间点元素4和5交换,然后换回。
结果顺序为:9,8,7,6,4,5,3,2,1,0
同样应将LBound添加到UBound中,而不是减去。如果减去则它仅适用于LBound为零。考虑50 = LBound,100 = UBound。这将导致For Ndx = 50到25.注意,这应该是FROM,TO计算而不是迭代计数计算。
这是我用于反转一维和二维数组的函数 他们还可以选择性地保留指定数量的标题行。
' Reverse array (one dimensional), optionally retain header rows.
Private Sub Reverse_Array_1d(ByRef Ary As Variant, Optional Header_Rows As Integer = 0)
Dim Dimension_Y As Integer ' Rows (height)
Dim Y_first As Long
Dim Y_last As Long
Dim Y_last_plus_Y_first As Long
Dim Y_next As Long
Dimension_Y = 1
Y_first = LBound(Ary, Dimension_Y) + Header_Rows
Y_last = UBound(Ary, Dimension_Y)
Y_last_plus_Y_first = Y_last + Y_first
Dim tmp As Variant
For Y = Y_first To Y_last_plus_Y_first / 2
Y_next = Y_last_plus_Y_first - Y
tmp = Ary(Y_next)
Ary(Y_next) = Ary(Y)
Ary(Y) = tmp
Next
End Sub
ReDim Ary(0 To 9) As Variant
Header_Rows = 1
Call Reverse_1d_Array(Ary, CInt(Header_Rows))
' Reverse array (two dimensional), optionally retain header rows.
Private Sub Reverse_Array_2d(ByRef Ary As Variant, Optional Header_Rows As Integer = 0)
Dim Dimension_Y As Integer ' Rows (height)
Dim Y_first As Long
Dim Y_last As Long
Dim Y_last_plus_Y_first As Long
Dim Y_next As Long
Dimension_Y = 1
Y_first = LBound(Ary, Dimension_Y) + Header_Rows
Y_last = UBound(Ary, Dimension_Y)
Y_last_plus_Y_first = Y_last + Y_first
Dim Dimension_X As Integer ' Columns (width)
Dim X_first As Long
Dim X_last As Long
Dimension_X = 2
X_first = LBound(Ary, Dimension_X)
X_last = UBound(Ary, Dimension_X)
ReDim tmp(X_first To X_last) As Variant
For Y = Y_first To Y_last_plus_Y_first / 2
Y_next = Y_last_plus_Y_first - Y
For X = X_first To X_last
tmp(X) = Ary(Y_next, X)
Ary(Y_next, X) = Ary(Y, X)
Ary(Y, X) = tmp(X)
Next
Next
End Sub
ReDim Ary(0 To 9, 0 To 3) As Variant
Header_Rows = 1
Call Reverse_2d_Array(Ary, CInt(Header_Rows))
答案 3 :(得分:0)
(1):一种简单但有限的解决方案,如果您的数据是由单个字符或回文组成的。假设您的数组名为vTmp,并且您可以选择一个不在数据中出现的定界符-我将使用“ |”。那么单行方法是:
vTmp = VBA.Split(VBA.StrReverse(VBA.Join(vTmp, "|")), "|")
它是有限的,因为每个值也会被反转。可以通过将索引替换为引用另一个数组中值的索引来解决,但这并不比其他解决方案简单。
(2):完整的解决方案,作为完整的Excel VBA功能:
Public Function rxReverse(uInput) As Variant
'' Simply reverses the order of items in input array.
'' If Input is singular, then it reverses the content.
''
'' v1 Rich Sulin 05-08-2019
Dim vTmp As Variant
Dim a1 As Long, a2 As Long, a3 As Long
Dim i As Long, j As Long
''
rxReverse = vbNullString
''
'' uInput is a Range object?
If TypeOf uInput Is Range Then
a1 = 1
If uInput.Columns.Count > 1 Then
a2 = uInput.Columns.Count
ReDim vTmp(a1 To a2) As Variant
a3 = 1 + (a2 - a1) / 2
For i = a1 To a3
j = a2 - i + 1
vTmp(j) = uInput(1, i).Value
vTmp(i) = uInput(1, j).Value
Next i
ElseIf uInput.Rows.Count > 1 Then
a2 = uInput.Rows.Count
ReDim vTmp(a1 To a2) As Variant
a3 = 1 + (a2 - a1) / 2
For i = a1 To a3
j = a2 - i + 1
vTmp(j) = uInput(1, i).Value
vTmp(i) = uInput(1, j).Value
Next i
Else
vTmp = VBA.StrReverse(VBA.CStr(uInput.Value))
End If
''
'' uInput is an Array?
Else
Select Case VBA.VarType(uInput)
Case Is >= vbArray
a1 = LBound(uInput)
a2 = UBound(uInput)
ReDim vTmp(a1 To a2) As Variant
a3 = 1 + (a2 - a1) / 2
For i = a1 To a3
j = a2 - i + 1
vTmp(j) = uInput(i)
vTmp(i) = uInput(j)
Next i
''
'' uInput is an irrelevant type?
Case vbNull, vbEmpty, vbError
Exit Function
''
'' uInput is a singular data; reverse it.
Case Else
vTmp = VBA.StrReverse(VBA.CStr(uInput))
End Select
End If
''
rxReverse = vTmp
''
'' If called from a Worksheet, vertically, then orient output array "vertically"
If VBA.IsObject(Application.Caller) Then
If Application.Caller.Rows.Count > 1 Then
rxReverse = Application.WorksheetFunction.Transpose(vTmp)
End If
End If
End Function