2016-08-02 19 views
4

Arbeiten mit Excel VBA.Wiederholen Sie eine Anzahl N Mal in einem Array

Ich versuche, ein Array mit repetitiven Mustern wie diese zu erstellen:

a = Array(1,1,1,1,1,2,2,2,2,2,2) 

Gibt es eine saubere Lösung (ohne durch eine Schleife zu gehen), dies zu tun? In fast jeder anderen statistischen Sprache erfolgt dies mit einer Wiederholungsfunktion. Zum Beispiel der „rep“ -Funktion in R oder die „repmat“ fuction in Matlab:

a = [repmat(1,1,5),repmat(2,1,6)] 

Der Grund, nicht alles hart Code in erster Linie, weil die tatsächliche Anordnung unterschiedliche Länge in Abhängigkeit von einigen anderen Variablen hat .

+0

Können Sie nicht verwenden 'Application.WorksheetFunction.Rept()'? – Brian

Antwort

4

Output: A, B, B, 1,1,1,2,2,2,2

Sub ArrayHack() 
    Dim a() 

    BuildArray a, "A", 1 
    BuildArray a, "B", 2 
    BuildArray a, 1, 3 
    BuildArray a, 2, 4 

    Debug.Print Join(a, ",") 

End Sub 

Function BuildArray(a As Variant, v As Variant, n As Integer) 
    Dim i As Integer, count As Integer 

    On Error Resume Next 
     count = UBound(a) 
     If Err.Number <> 0 Then 
      ReDim a(0) 
      count = -1 
     End If 
    On Error GoTo 0 

    ReDim Preserve a(count + n) 

    For i = 1 To n 
     a(count + i) = v 
    Next 

End Function 

Output: 1,1,1,1,1 , 2,2,2,2,2

Sub ArrayHack2() 
    Dim a 
    Dim s As String 
    s = Replace(String(5, ","), ",", 1 & ",") & Replace(String(5, ","), ",", 2 & ",") 
    s = Left(s, Len(s) - 1) 

    a = Split(s, ",") 

    Debug.Print Join(a, ",") 

End Sub 
+0

Ihre erste Lösung ist ziemlich elegant. Ich mag die Art, wie es ein Array flexibel redimieren kann. –

+0

Sehr geschätzt. Dies wird den Job machen und ist in der Tat flexibel. Offensichtlich gibt es keine eingebaute Funktion, die das angeht. Ich denke du und @JohnColeman haben diese Funktion im Grunde für mich geschaffen. Eine Schleife ist dann unvermeidlich. –

+0

Danke für das Häkchen! Es war eine interessante Frage. Es wäre interessant, John Colemans Antwort mit meiner eigenen zu kombinieren. –

0

Gefällt mir das?

Const U = 11          'U = (4 + Max(i)) * Max(i) + Max(j) 
Sub ManipulatingArray() 
Dim InputArray As String, i As Long, j As Long, MyArray(1 To U) As Variant 
For i = 0 To 1 
    For j = 1 To 5 + i 
     MyArray((4 + i) * i + j) = i + 1 
    Next 
Next 
Debug.Print Join(MyArray, ",") 
End Sub 

Der obige Code gibt Ihnen die Ausgabe als Ihr Beispiel.

+0

Dies ist nicht sehr flexibel. OP weiß bereits, wie man Arrays in einer Schleife initialisiert, aber fragt sich, ob es eine Möglichkeit gibt, solche expliziten Schleifen zu vermeiden. –

+0

@JohnColeman: Nur weil "das ist nicht sehr flexibel" nach Ihrer Definition bedeutet es nicht verdient, downvoted zu werden. Ganz zu schweigen von der OP entscheidet es –

+0

@ Anastasiya-Romanova 秀 Danke. Aber das ist nicht das, was ich wollte. –

2

Hier ist eine etwas flexible Funktion:

Function BuildArray(ParamArray params()) As Variant 
    Dim A As Variant, v As Variant 
    Dim i As Long, j As Long, k As Long, n As Long, m As Long, b As Long 

    n = UBound(params) 

    If n Mod 2 = 0 Then 
     b = params(n) 
     n = n - 1 
    End If 

    For i = 1 To n Step 2 
     m = m + params(i) 
    Next i 

    ReDim A(b To b + m - 1) 
    k = b 

    For i = 0 To n - 1 Step 2 
     v = params(i) 
     For j = 1 To params(i + 1) 
      A(k) = v 
      k = k + 1 
     Next j 
    Next i 

    BuildArray = A 
End Function 

Es nimmt eine beliebige Anzahl von Argumenten. Wenn eine gerade Anzahl von Argumenten vorhanden ist, werden sie in aufeinanderfolgende Paare der Form v,i aufgeteilt, wobei v ein Wert ist und i die Anzahl der Wiederholungen des Werts ist und das resultierende Array mit dem ersten Index 0 zurückgegeben wird. Wenn eine ungerade Zahl vorhanden ist der übergebenen Parameter wird der letzte Parameter als Basis des Arrays interpretiert. Zum Beispiel:

Sub test() 
    Dim A As Variant 

    A = BuildArray(1, 3, 2, 4) 'creates 0-based array [1,1,1,2,2,2,2] 
    'verify: 
    Debug.Print "A = " & LBound(A) & " to " & UBound(A) 
    Debug.Print "Items: " & Join(A, ",") 

    A = BuildArray(1, 3, 2, 4, 1) 'creates 1-based array [1,1,1,2,2,2,2] 
    'verify: 
    Debug.Print "A = " & LBound(A) & " to " & UBound(A) 
    Debug.Print "Items: " & Join(A, ",") 
End Sub 

Ausgang:

A = 0 to 6 
Items: 1,1,1,2,2,2,2 
A = 1 to 7 
Items: 1,1,1,2,2,2,2 
+0

Ich wünschte, ich hätte gedacht, ParamArray zu verwenden. Ich würde isBase1 gegenüber dem nicht gepaarten Wert bevorzugen. Es ist nervig, dass Sie keine optionalen Parameter mit einem ParamArray haben können. –

+0

@ThomasInzina Ja, ich wünschte mir, dass ich sowohl einen Paramarray als auch einen optionalen Parameter verwenden könnte (obwohl es vielleicht eine gewisse Art gibt - ich bin nicht 100% sicher, dass ich etwas nicht vermisse). Ich tendiere dazu, mehr Python-Programmierung als VBA-Programmierung zu machen, und oft fehlt mir etwas von Pythons Kraft und Flexibilität, wenn ich zu VBA zurückkehre. In Python wäre so etwas einfach. Meine Funktion könnte so modifiziert werden, dass das letzte optionale Argument "True" oder "False" anstelle von (oder zusätzlich zu) einem int sein könnte - wobei "True" vielleicht als "Base1" interpretiert wird. –