+ Rispondi al Thread
Visualizzazione dei risultati da 1 a 8 su 8

Discussione: Gestione di una matrice multidimensionale con spostamento

  1. #1
    BennyB non è in linea Scolaretto
    Post
    158

    Gestione di una matrice multidimensionale con spostamento

    Buongiorno.
    Ho un altro problema che mi assilla non poco.
    Devo gestire una matrice multidimensionale, che chiamerò sMatr , per semplicità.

    La matrice è così dimensionata: sMatr(10,4).
    Devo ordinare le varie righe secondo la logica seguente (faccio un esempio):

    E xx yyy 1
    B xx yyu 100
    A xy yuu 50
    B xx yyy 3
    F xc yyu 10
    A ww yyy 100

    deve risultare quanto segue:

    E xx yyy 1
    B xx yyu 100
    B xx yyy 3
    A xy yuu 50
    A ww yyy 100
    F xc yyu 10

    Quindi, la colonna di "ordinamento è sMatr(x,1), ma non è un ordinamento alfabetico.

    Ho impostato questo codice, parziale e deficitario:
    codice:
    Sub ElencoOrdAttributi(ByRef SortArray As Variant)
    Dim ArrayTemp As Variant
    Dim jj, ii, idest As Long
    
    
    ReDim ArrayTemp(1 To UBound(SortArray, 1), 1 To UBound(SortArray, 2))
    
    jj = 1
    ii = 1
    idest = 0
    While ii <= UBound(SortArray, 1)
        While jj <= UBound(SortArray, 1)
            If SortArray(ii, 1) = SortArray(jj, 1) Then
                idest = idest + 1
                For iContatore = 1 To UBound(SortArray, 2)
                    ArrayTemp(idest, iContatore) = SortArray(jj, iContatore)
                Next iContatore
                '-->Elimina la riga in SortArray
            End If
            jj = jj + 1
        Wend
        ii = ii + 1
    ElencoOrdAttributi = ArrayTemp
    Wend
    quello che manca è l'eliminazione della riga nella matrice chiamante. Mi sembra molto farraginoso, e credo ci siano soluzioni più semplici ed eleganti. Ci ho perso già un paio d'ore... se qualcuno può aiutarmi, intanto provo a rifletterci.

    Grazie.

  2. #2
    Ferrari_and non è in linea Scolaretto
    Post
    236
    Ciao, se no ricordo male uno dei migliori algortimi di ordinamento di un array era il bouble sort.
    Pernso sia applicapibe anche a matrici di dati.
    Purtroppo non sono riuscito a capire come sia costrutio la matrice dei dati e qundi con che criterio dovresti ordinali.

  3. #3
    BennyB non è in linea Scolaretto
    Post
    158
    Beh, conosco bene l'algoritmo, ma non è applicabile, in questo caso. Non si tratta di ordinare alfabeticamente la matrice.
    Prova a mettere in miglior vista l'esempio:

    E | xx | yyy |1
    B | xx | yyu | 100
    A | xy | yuu | 50
    B | xx | yyy | 3
    F | xc | yyy | 10
    A | ww| yyy |100


    Risultato:
    E | xx | yyy |1
    B | xx | yyu | 100
    B | xx | yyy | 3
    A | xy | yuu | 50
    A | ww| yyy |100
    F | xc | yyy | 10


    La matrice sMatr è composta da 10 righe (solo 6 sono rappresentate nell'esempio, per praticità) e 4 colonne (i dati indicati non sono significativi). Quello che conta è che l'ordinamento delle righe segue quelle mostrato: cioè, partendo dalla prima riga, si cerca se il dato della prima colonna di tutte le altre righe corrisponde, e allora, si spostano sotto, e così via scorrendo le righe. L'esempio consiste in caratteri alfanumerici, ma in realtà sono stringhe; non fa differenza, ovvio, perché le stringhe stesse si ripetono.
    Spero sia più chiaro.

  4. #4
    Ferrari_and non è in linea Scolaretto
    Post
    236
    Si in questo caso il booble sort non è assolutamente applicabile.
    Unico modo mi sembra quello di partire dal primo elemento e spostare gli alri con = valore sotto. e ripetere l'oprazione per gli altri elementi

  5. #5
    BennyB non è in linea Scolaretto
    Post
    158
    Ho scritto una specie di soluzione, e sembra funzionare, tranne che per il passaggio degli array. Al solito, VBA mi manda ai matti con gli array...
    Credo ci siano poche correzioni da fare, ma non riesco proprio a vederle. Spero qualcuno possa aiutarmi.
    Sono partito da questa routine che imposta una matrice di esempio:
    codice:
    Sub provaar()
    Dim bb(5, 2) As Variant
    bb(1, 1) = "D"
    bb(1, 2) = "-"
    bb(2, 1) = "B"
    bb(2, 2) = "--"
    bb(3, 1) = "A"
    bb(3, 2) = "---"
    bb(4, 1) = "C"
    bb(4, 2) = "----"
    bb(5, 1) = "A"
    bb(5, 2) = "-----"
    ElencoOrdAttributi (bb)
    'elenca la matrice finale
    For iTd = 1 To UBound(bb, 1)
        For iCont = 1 To 2
            Debug.Print bb(iTd, iCont)
        Next iCont
    Next iTd
    End Sub
    La funzione di elaborazione è la seguente (va affinata, ma al momento fa quello che deve fare):
    codice:
    Public Function ElencoOrdAttributi(ByRef SortArray As Variant) As Variant
    Dim ArrayTemp As Variant
    Dim jj, ii, idest, iLimC1 As Long
    
    ReDim ArrayTemp(1 To UBound(SortArray, 1), 1 To UBound(SortArray, 2))
    
    jj = 1
    ii = 1
    idest = 0
    iLimC1 = UBound(SortArray, 1)
    While ii <= iLimC1
        idest = idest + 1
        Call spostaRiga(SortArray, ArrayTemp, 1, idest)
        For jj = 1 To UBound(SortArray, 1)
        'While jj <= UBound(SortArray, 1)
            If SortArray(jj, 1) = ArrayTemp(idest, 1) And SortArray(jj, 1) <> vbNullString Then
                idest = idest + 1
                Call spostaRiga(SortArray, ArrayTemp, jj, idest)
                iLimC1 = iLimC1 - 1
            End If
        Next jj
        ii = ii + 1
    Wend
    'trasferisce l'array
    ElencoOrdAttributi = ArrayTemp
    For iTd = 1 To UBound(ArrayTemp, 1)
        For iCont = 1 To 2
            Debug.Print ArrayTemp(iTd, iCont)
        Next iCont
    Next iTd
    End Function
    a sua volta la function utilizza questa routine:
    codice:
    Sub spostaRiga(sArray1 As Variant, sArray2 As Variant, iRiga1, iRiga2)
    Dim iAA, iBB
    For iAA = 1 To UBound(sArray1, 2)
        sArray2(iRiga2, iAA) = sArray1(iRiga1, iAA)
    Next iAA
    'elimina Riga spostata
    For iAA = iRiga1 To UBound(sArray1, 1) - 1
        For iBB = 1 To 2
            sArray1(iAA, iBB) = sArray1(iAA + 1, iBB)
        Next iBB
    Next iAA
    'vuota ultima riga
    iAA = UBound(sArray1, 1)
    For iBB = 1 To 2
        sArray1(iAA, iBB) = vbNullString
    Next iBB
    End Sub
    Sono certo che si può fare in modo più semplice, ma ci ho già perso troppo tempo.
    Tutto bene, in definitiva fino al passaggio dell'array a quello della function, (questo)
    codice:
    ElencoOrdAttributi = ArrayTemp
    lo spostamento dei dati a 'arrayTemp' risulta corretto, infatti, i cicli di verifica successivi mostrano l'avvenuto spostamento, non così, invece, il trasferimento a 'ElencoOrdAttributi', sebbene non mi dia errore.
    Infatti, se ripeto i cicli dopo l'ipotetica assegnazione all'array 'bb' (questo)
    codice:
    ElencoOrdAttributi (bb)
    , non noto alcun cambiamento rispetto all'inizio.
    Sapete dirmi dove sbaglio?
    Ultima modifica di BennyB; 27-05-2020 15:08 

  6. #6
    Ferrari_and non è in linea Scolaretto
    Post
    236
    Se ti aspertti che il valore di BB mutino dopo la chiamata dell funzione in questo caso devi passare byref pure gli array anche nella sub per modificare il contenuto degli arry. Se non sbaglio se non indicato il default è byval.

  7. #7
    BennyB non è in linea Scolaretto
    Post
    158
    Intendi questo?
    codice:
    Sub spostaRiga(ByRef sArray1 As Variant, ByRef sArray2 As Variant, iRiga1, iRiga2)
    No, non cambia nulla. Avevo già provato, ma anche in questo caso l'array 'bb' resta immutato.

  8. #8
    BennyB non è in linea Scolaretto
    Post
    158
    Alla fine, ci sono riuscito. Il problema è sempre legato alle matrici, come dicevo, che per essere passate alle function devono essere dinamiche.
    Quindi, anzitutto le dimensioni della matrice di partenza non possono essere poste nella dichiarazione (altrimenti VBA non la interpreta come dinamica).
    In più, le istruzioni di passaggio delle matrici devono sempre specificare negli argomenti che si tratta di matrici dinamiche multidimensionali, al che non posso passare semplicemente 'bb' o 'sArray1', bensì 'bb()' e 'sArray1()', specificando anche che la matrice risultante della function sarà dello stesso tipo, quindi indicando il tipo di dati come 'variant()'.

    Tenendo conto di questa logica, ho modificato il codice, e ora funziona.
    Non so se sarà utile a qualcuno... magari, sì, perché queste situazioni sono rare, ma poi fanno perdere un sacco di tempo (a chi non sa le cose come me, naturalmente).
    Ringrazio comunque Ferrari_and per i suggerimenti.
    Riporto il codice corretto.

    SUB DI PARTENZA
    codice:
    Sub provaar()
    Dim bb() As Variant
    ReDim bb(1 To 7, 1 To 2)
    'Dim bb(7, 2) As Variant (questa era errata)
    bb(1, 1) = "D"
    bb(1, 2) = "-"
    bb(2, 1) = "B"
    bb(2, 2) = "--"
    bb(3, 1) = "A"
    bb(3, 2) = "---"
    bb(4, 1) = "C"
    bb(4, 2) = "----"
    bb(5, 1) = "A"
    bb(5, 2) = "-----"
    bb(6, 1) = "C"
    bb(6, 2) = "-----"
    bb(7, 1) = "D"
    bb(7, 2) = "-----"
    
    bb = ElencoOrdAttributi(bb) 'assegnazione corretta
    'Stampa dell'elenco finale passato a 'bb'
    For iTd = 1 To UBound(bb, 1)
        For iCont = 1 To 2
            Debug.Print bb(iTd, iCont)
        Next iCont
    Next iTd
    End Sub
    FUNCTION DI ELABORAZIONE
    codice:
    Public Function ElencoOrdAttributi(SortArray() As Variant) As Variant()
    Dim ArrayTemp() As Variant
    Dim jj, ii, idest, iLimC1 As Long
    '
    ReDim ArrayTemp(1 To UBound(SortArray, 1), 1 To UBound(SortArray, 2))
    jj = 1
    ii = 1
    idest = 0
    iLimC1 = UBound(SortArray, 1)
    While ii <= iLimC1
        idest = idest + 1
        Call spostaRiga(SortArray, ArrayTemp, 1, idest)
        For jj = 1 To UBound(SortArray, 1)
            If SortArray(jj, 1) = ArrayTemp(idest, 1) And SortArray(jj, 1) <> vbNullString Then
                idest = idest + 1
                Call spostaRiga(SortArray, ArrayTemp, jj, idest)
                iLimC1 = iLimC1 - 1
            End If
        Next jj
        ii = ii + 1
    Wend
    '
    'stampa l'elenco modificato ora contenuto in 'ArrayTemp'
    For iTd = 1 To UBound(ArrayTemp, 1)
        For iCont = 1 To 2
            Debug.Print ArrayTemp(iTd, iCont)
        Next iCont
    Next iTd
    'assegna la matrice per il trasferimento finale
    ElencoOrdAttributi = ArrayTemp
    End Function
    SUB DI SUPPORTO ALLA FUNCTION
    codice:
    Sub spostaRiga(sArray1() As Variant, sArray2() As Variant, iRiga1, iRiga2)
    Dim iAA, iBB
    For iAA = 1 To UBound(sArray1, 2)
        sArray2(iRiga2, iAA) = sArray1(iRiga1, iAA)
    Next iAA
    'elimina Riga spostata
    For iAA = iRiga1 To UBound(sArray1, 1) - 1
        For iBB = 1 To 2
            sArray1(iAA, iBB) = sArray1(iAA + 1, iBB)
        Next iBB
    Next iAA
    'vuota ultima riga
    iAA = UBound(sArray1, 1)
    For iBB = 1 To 2
        sArray1(iAA, iBB) = vbNullString
    Next iBB
    End Sub
    Saluti.

+ Rispondi al Thread

Tag per questa discussione

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi