#arrays #excel #vba #loops
#массивы #превосходить #vba #петли
Вопрос:
У меня есть 2 вложенных цикла в массиве, но, насколько я понимаю, мне нужен третий, который я не в состоянии реализовать.
У меня есть следующие данные (желтым цветом):
Текущий код вычисляется, как указано в столбце Фактическое поведение:
Dim arr, outarr as Variant Dim lastc, lastr as long lastc = 2 lastr = Cells(ws.Rows.count, lastc).End(xlUp).Row arr = Range(Cells(2, lastc), Cells(lastr, lastc)) cnt = ((UBound(arr, 1) - 1) * UBound(arr, 1)) / 2 k = 1 ReDim outarr(1 To cnt, 1 To 1) For i = LBound(arr, 1) 1 To UBound(arr, 1) For j = LBound(arr, 1) To i - 1 outarr(k, 1) = arr(j, 1) - arr(i, 1) k = k 1 Next j Next i
Желаемое поведение было бы для значений от 1.1 до 6.1, чтобы в результате сохранить минимальное значение в этом диапазоне. 10 — 0 = 10, но мне нужно фактическое минимальное значение в этом диапазоне (от 1,6 до 6,6), а минимальное значение будет 10 — 40 = -30.
Действительно важно, чтобы минимальное значение всегда вычислялось как первое значение диапазона — X значения диапазона. Первое значение в данном цикле является константой.
Я считаю, что третий цикл необходим для хранения минимального значения, а затем вставьте это значение в outarr, но пока мне это не удалось.
Спасибо вам за вашу помощь.
Комментарии:
1. Я не уверен, правильно ли я понимаю часть минимального значения.. Для
B7-B3
, разве минимальное значение не будет5 - 40
? иB7-B2
, минимальное значение будет0 - 40
?2. @Raymond Wu Обновил мой запрос. Спасибо, что указали на это. Первое значение в диапазоне является константой, расчет основан на (первое значение — значение X, первое значение — значение Y…..).
3. Извините, я все еще не понимаю, потому
B5-B3
что выход равен 25 , но разве это не минимум30 - 40
?4. @Raymond Wu Да, вы правы. Я просто не рассчитал это, так как желаемое поведение объясняется в примере B7. Но да, минимум будет — 10.
5. @Raymond У меня еще один вопрос, Рэймонд. Этот цикл является частью большего цикла, и когда я пытаюсь получить доступ к следующему циклу, outputindex увеличивается на 1. Есть идеи, почему? Количество строк, размер массива-все идентично. Спасибо.
Ответ №1:
Вместо того, чтобы делать еще один цикл, я записываю наименьшее значение в каждом цикле и сравниваю его с новым значением во внутреннем цикле:
Option Explicit Private Sub Test() Const startRow As Long = 2 Const valueCol As Long = 2 Const outputCol As Long = 4 Dim ws As Worksheet Set ws = ThisWorkbook.Worksheets("Sheet1") Dim lastRow As Long lastRow = ws.Cells(ws.Rows.Count, valueCol).End(xlUp).Row Dim inputArr As Variant inputArr = ws.Range(ws.Cells(startRow, valueCol), ws.Cells(lastRow, valueCol)).Value Dim outputSize As Long outputSize = ((UBound(inputArr, 1) - 1) * UBound(inputArr, 1)) / 2 Dim outputIndex As Long Dim outputArr As Variant ReDim outputArr(1 To outputSize, 1 To 1) As Variant Dim i As Long Dim n As Long Dim currFirst As Long Dim currLowest As Long For i = 2 To UBound(inputArr, 1) currFirst = inputArr(i, 1) currLowest = currFirst - inputArr(i - 1, 1) For n = i - 1 To 1 Step -1 Dim testLowest As Long testLowest = currFirst - inputArr(n, 1) If testLowest lt; currLowest Then currLowest = testLowest outputIndex = outputIndex 1 outputArr(outputIndex, 1) = currLowest Next n Next i ws.Cells(startRow, outputCol).Resize(UBound(outputArr, 1)).Value = outputArr End Sub
Комментарии:
1. Спасибо тебе, Рэймонд. Пришлось внести изменения в некоторые части кода, чтобы удовлетворить мои потребности, но работает отлично.
Ответ №2:
Я считаю, что это дает желаемые результаты.
Вместо того, чтобы добавлять 3-й вложенный цикл в микс, я добавил дополнительный вспомогательный цикл на первый уровень.
Пожалуйста, обратите внимание: это должно дать вам хорошее представление о том, как подойти к этому с меньшей сложностью, чем к другому уровню For Next
цикла, но из-за позиционирования производительность будет снижаться по мере роста итераций.
Я переименовал некоторые переменные, чтобы они были более описательными (за исключением x
того, что я обленился).
Объяснение находится ниже кода, вот переработанный раздел цикла.
OutputCounter = 1 For LayerOneStep = LBound(ValueArray, 1) To UBound(ValueArray, 1) ReDim TempArray(1 To LayerOneStep) For x = 1 To UBound(TempArray) TempArray(x) = ValueArray(x, 1) Next x For LayerTwoStep = LBound(ValueArray, 1) To LayerOneStep - 1 MaxValue = WorksheetFunction.Max(TempArray) TempValue = (ValueArray(LayerOneStep, 1) - ValueArray(LayerTwoStep, 1)) If ValueArray(LayerOneStep, 1) = 0 Or ValueArray(LayerTwoStep, 1) = 0 Then OutputArray(OutputCounter) = TempValue OutputCounter = OutputCounter 1 ElseIf TempValue lt; ValueArray(LayerOneStep, 1) - MaxValue Then OutputArray(OutputCounter) = TempValue OutputCounter = OutputCounter 1 Else OutputArray(OutputCounter) = ValueArray(LayerOneStep, 1) - MaxValue OutputCounter = OutputCounter 1 End If Next LayerTwoStep Next LayerOneStep
TempArray()
используется для хранения ваших сгруппированных значений. Т. е. B3 amp; B2 или B5 amp; B4 amp; B3 amp; B2 и т. Д. Это достигается путем присвоения значений из столбца B строки 2 независимо от того, до какой строки находится счетчик LayerOne. Значения назначаются из существующегоValueArray
массива, а не каждый раз повторно обращаются к рабочему листу.- Назначение его таким образом позволяет нам использовать
WorksheetFunction.Max()
функцию для поиска наибольшего числа в наборе. (имейте в виду, как указано выше, не самый эффективный способ) - Затем мы используем некоторые переменные для назначения некоторых вычислений.
MaxValue
Как указано выше, иTempValue
это подход x-y — тот же результат, что и формулы рабочего листа. - Затем мы используем некоторую
If...Then...Else
логику, чтобы начать разработку абсолютного минимального значения на основе диапазона вычислений. If
Условия Fist проверяют, является ли какое-либо значение частьюTempValue
вычисления равным нулю (0). Если это так, он возвращает некоторые забавные результаты, так что это гарантирует, что мы перейдем к результату x — 0 или 0 — yOutputArray
.- Во — вторых, проверяется, соответствует ли
TempValue
вычисление значению меньше x —MaxValue
. Если да, то он возвращаетсяTempValue
вOutputArray
. - В противном случае мы возвращаем x —
MaxValue
вOutputArray
.
Результат вышеупомянутого кодекса;