Как вернуть ранг каждого двойного в массиве, когда есть повторяющиеся значения? - PullRequest
0 голосов
/ 29 октября 2019

Если мой входной массив равен (10,10,20,20,30,30,40,40,50,50), я хотел бы получить простой фрагмент кода, который вернул бы (1,2,3,4,5, 6,7,8,9,10). Я пытаюсь реализовать классификацию ABC, и в настоящее время я использую этот код:

    For i = 1 To noA 'noA number of items should be classified as "A"
        'return the item number with the i'th largest number in arrTembABC
        intTemp = Application.Match(WorksheetFunction.Large(arrTempABC, i), arrTempABC, True)
        'assign the category "A" to 'intTemp' item number
        SKUinfo(intTemp, 12) = "A"
    Next i

    'some printing code

Проблема с приведенным выше кодом заключается в том, что при наличии повторяющихся значений всегда возвращается позиция первого экземпляра. Любому другому номеру элемента с таким же значением не присваивается категория.

Так что для рассмотренного выше массива (см. «Среднее значение») код классифицирует только первый экземпляр каждого дублированного значения, а остальныепусто (см. «ABC_CategCry»)

1 Ответ

0 голосов
/ 31 октября 2019

Я прибег к сортировке массива, в котором хранятся значения, в то время как их позиции хранятся в отдельном массиве. Я публикую ниже весь подпункт, который выполняет классификацию ABC на основе объема или стоимости (= средний объем * стоимость). Я пытался комментировать в информативной форме, но буду благодарен за любые вопросы для разъяснения или за комментарии о том, как улучшить ясность.

Sub ABCclass(ByRef swtcABCclass As Integer, ByRef prcA As Double, ByRef prcB As Double, _
    ByRef prcC As Double)
    Dim arrTempABC() As Double, i As Integer, j As Integer, intTemp As Integer, tempABC As Double
    Dim noA As Integer, noB As Integer, noC As Integer, arrTempTSno() As Integer

    ReDim arrTempABC(1 To tsTot)
    ReDim arrTempTSno(1 To tsTot)


    'populate the array that holds the values by which we classify the SKUs
    If swtcABCclass = 1 Then 'ABC based on volume*value
        For i = 1 To tsTot
            arrTempABC(i) = SKUinfo(i, 11) * SKUinfo(i, 5) 'average monthly volume*value (cost)
            arrTempTSno(i) = i 'just hold the position (ascending number of the timeseries/SKU)
        Next i
    ElseIf swtcABCclass = 2 Then 'ABC based on volume
        For i = 1 To tsTot
            arrTempABC(i) = SKUinfo(i, 11) ' average monthly volume
            arrTempTSno(i) = i
        Next i
    End If

    'find the limits of each class (in terms of percentages of SKUbase)
    noA = WorksheetFunction.RoundDown(tsTot * prcA, 0) 'first prcA% of the tsTot (number of timeseries or SKUs) are in class A
    noB = noA + WorksheetFunction.RoundDown(tsTot * prcB, 0)
    noC = tsTot

    'sort arrTempABC while saving the positions in a seperate array
    For i = 2 To tsTot
        tempABC = arrTempABC(i)
        intTemp = arrTempTSno(i)
        For j = i - 1 To 1 Step -1
            If arrTempABC(j) >= tempABC Then Exit For
            arrTempABC(j + 1) = arrTempABC(j)
            arrTempTSno(j + 1) = arrTempTSno(j)
        Next
        arrTempABC(j + 1) = tempABC
        arrTempTSno(j + 1) = intTemp
    Next

    'now that i have the sorted positions, i can just assign the categories
    For i = 1 To noA 'noa number of items should be classified as "A"
        SKUinfo(arrTempTSno(i), 12) = "A"
    Next i
    For i = noA + 1 To noB 'nob - (noa +1) number of items should be classified as "B"
        SKUinfo(arrTempTSno(i), 12) = "B"
    Next i
    For i = noB + 1 To noC 'noc - (nob +1) number of items should be classified as "C"
        SKUinfo(arrTempTSno(i), 12) = "C"
    Next i

End Sub
...