Умножить 1D-массив на 1D-массив или константу - VBA - PullRequest
0 голосов
/ 08 января 2020

Имея риск быть топи c, я решил поделиться кодом, Q & A-style . Если общее мнение таково, что это будет не так c Я буду рад удалить, если это будет необходимо.

Справочная информация:

Мне было интересно, можно ли было вернуть 1D-массив из умножения другого 1D-массива либо на постоянное значение, либо на третий 1D-массив (того же размера) без итерации.

Таким образом, процесс, который я ищу, будет выглядеть так:

  • Умножьте на Константу> Производите {3,6,9} непосредственно из {1,2,3}*3
  • Умножить на массив> Производная {3,8,15} непосредственно из {1,2,3}*{3,4,5}

Пример кода:

Я видел вопросы, касающиеся этой темы c, но я еще не видел ответа, который бы делал это без итерации. Самое близкое, что я видел, это @SiddharthRout, на внешнем форуме.

Но обычно можно выбрать итерацию:

  • Умножить на постоянную

Sub Test()
    
    Dim arr1 As Variant: arr1 = Array(1,2,3)
    Dim y As Long, x As Long: x = 3 'Our constant
    
    For y = LBound(arr1) To UBound(arr1)
        arr1(y) = arr1(y) * x
    Next y
    
    End Sub
  • Умножить на массив

Sub Test()

Dim arr1 As Variant: arr1 = Array(1, 2, 3)
Dim arr2 As Variant: arr2 = Array(3, 4, 5)
Dim y As Long

For y = LBound(arr1) To UBound(arr1)
    arr1(y) = arr1(y) * arr2(y)
Next y

End Sub

Вопрос:

Как вы могли получить 1D - массив от умножения другого 1D-массива на любую константу или другой (одинакового размера) 1D-массив без итерации?

1 Ответ

0 голосов
/ 08 января 2020

Я обнаружил, что ключ к ответу будет лежать в MMULT, возвращая массив из умножающихся строк * столбцов.


Multiply 1D-массив по константе

Sub Multiply_1D_byConstant()

Dim arr1 As Variant: arr1 = Array(1, 4, 3, 5, 10, 15, 13, 11, 6, 9)

With Application

    Dim x As Long: x = 3 'Our constant
    Dim y As Long: y = UBound(arr1) + 1

    Dim arr2 As Variant: arr2 = .Evaluate("TRANSPOSE(ROW(" & x + 1 & ":" & x + y + 1 & ")-ROW(1:" & y + 1 & "))")
    Dim arr3 As Variant: arr3 = .Evaluate("TRANSPOSE(ROW(1:" & y & "))")
    Dim arr4 As Variant: arr4 = .Index(.MMult(.Transpose(arr1), arr2), arr3, 1)

End With

End Sub

Здесь .Evaluate быстро вернет 1D-массив n раз нашей константы, где n равно Ubound(arr1)+1. В приведенном выше случае: {3,3,3,3,3,3,3,3,3,3}

We чем .Transpose arr1 в нашем .MMult(.Transpose(arr1), arr2), который вернет 2D-массив. Поскольку нам нужно было бы повторить это, мы скорее сократим массив, чтобы извлечь 1D-массив на .Index. Результат описанного выше будет:

{3, 12, 9, 15, 30, 45, 39, 33, 18, 27}

Чтобы визуализировать, как это работает: .MMult вернет 2D-массив из приведенного выше примера, например, так:

enter image description here

Тогда, потому что мы в основном задаем .Index массив, подобный {1,2,3,4,5,6,7,8,9,10}, но динамически c, для строк и просто 1 для первого столбца , .Index вырежет 1D-массив из этого 2D-массива:

enter image description here


Умножьте 1D-массив на 1D-массив

Это будет работать примерно так же. Давайте представим следующее:

Sub Multiply_1D_by1D()

Dim arr1 As Variant: arr1 = Array(1, 4, 3, 5, 10, 15, 13, 11, 6, 9)
Dim arr2 As Variant: arr2 = Array(2, 1, 4, 1, 2, 3, 2, 5, 2, 1)

With Application

    Dim y As Long: y = UBound(arr1) + 1
    Dim arr3 As Variant: arr3 = .Evaluate("TRANSPOSE(ROW(1:" & y & "))")
    Dim arr4 As Variant: arr4 = .Index(.MMult(.Transpose(arr1), arr2), arr3, arr3)

End With

End Sub

На этот раз мы не говорим .Index извлечь тот же самый постоянный первый столбец из результата .MMult, но мы даем ему тот же массив значений как строки. Эти значения должны быть одномерным массивом, поэтому мы используем .Evaluate для динамического возврата массива. Таким образом, приведенное выше возвращает 1D-массив, например:

{2, 4, 12, 5, 20, 45, 26, 55, 12, 9}

Чтобы визуализировать, как это работает: .MMult вернет 2D-массив из приведенного выше примера, например, так:

enter image description here

Тогда, потому что мы в основном даем .Index два массива, как {1,2,3,4,5,6,7,8,9,10}, но динамически c, .Index будет срезать 1D- массив из этого 2D-массива:

enter image description here


Таким же образом вы можете вырезать любой 1D-массив из 2D-массива, используя .Index до тех пор, пока вы оба указываете параметр rows и columns с допустимым 1D-массивом. Надеюсь, это кому-нибудь пригодится.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...