Trier un tableau sur VBA

Suite ...

Nouvelle version, je suis passé de 5 minutes 34 secondes à 36 secondes sur un jeu test de 1000 individus !

En réalité, avec mon programme bourrin, j'ai eu un cas tordu : en quelque sorte Paul voulait plusieurs choix dont Pampelune en choix 6 où il était le 6ème mieux placé pour 5 places. Mais son choix 1 n'était pas dispo ... ma moulinette lui a affecté son choix 3, a donc libéré ses autres choix dont Pampelune. Et dans un tour d'affectation suivant, Pierre a choppé un de ces choix mais a aussi libéré le choix Pampelune qui du coup revenait à Pierre mais qui était déjà affecté !

Alors je me suis dit qu'il fallait que je libère les choix avant de faire tourner la moulinette ! Et c'est là tout le génie de curulis57 car c'est ce que tu faisais in fine. L'histoire ne s'arrête pas là car à la fin de la phase préparation je m'attendais à avoir le résultat. Et non ... mais c'est sans compter encore une seconde pépite de la présentation en ascenseurs de curulis57 : les affectations sont les premières des listes verticales.

De toute façon, même avec 36 secondes, le même jeu d'essai avec le code de curulis57 met 30 secondes !

Autre point expérimenté ...

On (moi aussi) parle souvent de base de données dans excel, mais ce ne sont que des listes à la Prévert !

J'ai donc cherché à mettre des clés secondaires pour accéder directement à un "enregistrement"-ligne. Ce que j'ai fait en ajoutant le n° de ligne et en mettant en place un TCD qui me donne les n° de lignes correspondant aux différents choix d'un individu.

capture d ecran 160

A vrai dire, je ne sais pas si cela a accéléré ou pas (par rapport à des Find en série) mais c'est plus confortable car assez visuel.

Prochaine étape : traduire tout ce bazar en utilisant des Array (et des dico sans doute pour les clés secondaires). Plus des recherches par dichotomie si nécessaire (plus rapide que le séquentiel).

On verra cela ce week end !

Salut les amis !

Je suit le sujet attentivement, bien qu'il dépasse mes compétences et que je n'ai pas le temps de me plonger dans le code en ce moment.

Utiliser une carte graphique de type CUDA pour accélérer le calcul pourrait être envisagé sur ce type de problématique non ? Plus simple et moins onéreux que du cluster ?

(Sinon tu demande à Google, si j'en crois les informations d'hier ils ont créé la machine à calculer la plus rapide au monde :p)

Girodo,

Info très intéressante ! merci Girodo

Me revoilà !

Après être passé de 5 minutes 34 secondes à 36 secondes sur un jeu test de 1000 individus, j'en suis maintenant à 5 secondes sur le même jeu et avec ma petite config i3 ... grâce à l'emploi de array et de dico faisant office de pseudo base de données avec clés secondaires (clé individu et clé zone).

Ouf !

Option Base 1
Sub Affecter()
Dim zone() As Variant
Dim data() As Variant

    [debut] = Now

    zone = [Tzones].Value
    Set nb = CreateObject("Scripting.Dictionary") ' effectif par zone
    For i = 1 To UBound(zone)
        nb(zone(i, 1)) = zone(i, 2)
    Next

    Sheets("Data").ListObjects(1).Sort.Apply
    data = [Tdata].Value
    Set z = CreateObject("Scripting.Dictionary") ' zone contient individu et choix dans l'ordre des points
    Set c = CreateObject("Scripting.Dictionary") ' choix par individu
    For i = 1 To UBound(data)
        z(data(i, 3)) = z(data(i, 3)) & data(i, 1) & "," & data(i, 4) & "|"
        c(data(i, 1)) = c(data(i, 1)) & data(i, 3) & "," & data(i, 4) & "|"
    Next

    Do
        drapeau = True
        For Each lieu In z.Keys
            tz = Split(z(lieu), "|")
            For i = 0 To Application.Min(UBound(tz), nb(lieu)) - 1
                individu = Split(tz(i), ",")(0)
                choix = Split(tz(i), ",")(1)
                tc = Split(c(individu), "|")
                For ii = 0 To UBound(tc) - 1
                    autrelieu = Split((tc(ii)), ",")(0)
                    autrechoix = Split((tc(ii)), ",")(1)
                    If autrechoix > choix Then
                        drapeau = False
                        c(individu) = Replace(c(individu), autrelieu & "," & autrechoix & "|", "")
                        z(autrelieu) = Replace(z(autrelieu), individu & "," & autrechoix & "|", "")
                    End If
                Next
            Next
        Next
    Loop Until drapeau

    With Sheets("Resultat").ListObjects(1)
        If Not .DataBodyRange Is Nothing Then .DataBodyRange.Delete
        For Each lieu In z.Keys
            tz = Split(z(lieu), "|")
            For i = 0 To Application.Min(UBound(tz), nb(lieu)) - 1
                individu = Split(tz(i), ",")(0)
                .ListRows.Add
                .DataBodyRange(.ListRows.Count, 1).Value = individu
                .DataBodyRange(.ListRows.Count, 2).Value = lieu
            Next
        Next
        .Sort.Apply
    End With

    Sheets("Resultat").Select
    [fin] = Now
    MsgBox "Terminé !"

End Sub

Je vais maintenant tester un jeu de 10.000 individus pour vérifier la capa mémoire.

Salut Steelson,

chapeau bas, my Lord!

Depuis le début, bien que n'y connaissant rien là-dedans, je me doutais que c'était un truc pour Dico... et voilà!

La hiérarchie est respectée et c'est très bien ainsi : c'est ça le ouf ?!

Ça fait longtemps que je sais devoir me coller à cette hydre Dico incompréhensible pour mon petit cerveau BASIC!

Respect!

A+

Quelques minutes (< 3 mn) pour 10.000 selon le nombre de places dispo pour chaque zone

Le plus long est presque de construire le jeu car il ne faut pas tirer au sort 2 fois le même choix !

Merci à toi car ta propre analyse a réussi à me simplifier le code.

Bonjour,

Chapeau bas Steelson ! Ton dernier programme s'est terminé en 7 minutes pour les 150 000 lignes !!! Le problème est qu'il y a des individus qui sont affectés sur plusieurs zones à la fois, ce qui ne devrait pas être permis.

@Curulis : le programme s'est bien terminé, le problème c'est que je ne vois pas comment vérifier les données vu que les affectés sont en gras ?

Salut Denis,

ça avance, je vois...

Perso, avec ma nouvelle boucle, j'annonce 90 sec. sur ton fichier initial de 28.000 lignes.

Le résultat vient de tomber mais, comme tu t'en doutes, je n'ai pas encore eu le temps de faire les vérifications d'usage.

Possible d'envoyer un fichier-bidon de 150.000 lignes par mail ?

L'histoire n'est pas terminée!

A+

Ok je t'envoie ça par mél

Chapeau bas Steelson ! Ton dernier programme s'est terminé en 7 minutes pour les 150 000 lignes !!!

Ok donc problème ... que je n'avais pas encore rencontré (enfin si, mais avant une correction).

Je pense néanmoins qu'à un certain niveau, il soit possible qu'on "boucle" sur des cas particuliers et dans ce cas il faut une toute dernière vérification pour éliminer les doublons moins positionnés.

Je viens de vérifier sur mes 10000 construits au hasard et je n'en ai pas.

J'aimerais bien avoir ton jeu d'essai (s'il est possible de l'anonymiser), éventuellement par mp via cjoint.com.

Pas vu de fichier, Denis...

De mon côté, j'ai fait un peu d'analyse du sujet ...

Comme pour toi Philippe, le principe est que dès qu'un individu est éligible pour un lieu (car "dans les premiers" en terme de points), tous ses autres choix (> choix courant) sont éliminés. On pourrait trouver un doublon si malheureusement un individu a noté 2 choix à égalité (même N°).

L'autre cause inhérente à la solution dico est que la longueur d'un élément soit "fini" et qu'un dépassement se produise. Dans ce cas les données dans le dico seraient tronquées. Je n'ai pas trouvé dans la littérature une limite quelconque mais peut-être que c'est le cas (je ne vois pas d'autres causes). Dans ce cas, il faut revenir à ta solution ou ne solution hybride dico/array.

Effectivement le taille maximale est de 300 ko par mp, je n'avais pas remarqué vu qu'il n'y a pas eu de message d'erreur.

Je vous l'envoie ici en .zip vu que la taille maximale autorisée est supérieure sur le forum à celle autorisée par MP.

Ce jeu de données n'est pas le jeu réel mais on peut trouver des doublons avec le programme de Steelson.

9essai-vba1.zip (899.98 Ko)

Salut les gars,

Á CONFIRMER, après vérif' du code et des résultats et, avant la séance de domestication de Dico qui va devoir rendre gorge : 9'20" pour mouliner tes 150.000 lignes!

La suite en soirée. Là, je n'ai plus le temps!

A+

6mn20 avec en effet des doublons que je vais analyser. Cela va prendre un peu de temps car je vais me faire un onglet "log" pour chaque pas de calcul concernant cet individu et ces lieux !


J'ai vu qu'il y avait des doublons dans les points, cela contredit la discussion que nous avions tenue !

Bon, ce n'est pas forcément la cause, quoique !!

Un point indécis a été soulevé par Steelson : quid lorsque 2 individus ont le même nombre de points pour une même zone?

2 individus ne peuvent pas avoir le même nombre de points s'il ne reste qu'une place. Un individu est avantagé manuellement avant le classement en comparant la situation précise des 2 individus avec d'autres critères que ceux indiqués.

Faudra plus de précisions quant à ta façon de procéder pour effectuer ce classement manuel (j'ai évidemment ma petite idée) pour effectuer cette manip' AVANT de lancer le calcul.

@curulis57 : il n'est pas nécessaire de reproduire ce traitement manuel puisqu'il est déjà pris en compte dans les données que je dois traiter.


J'ai vu aussi que certaines n'avaient pas de choix "1" ! On en avait parlé ici ... mais encore une fois ce n'est pas forcément la cause non plus.

- Concernant ton message de 02 h17 :

- j'ai dû couper le tableau sinon il ne passait pas dans le forum parce que trop gros, donc certains individus n'ont pas l'intégralité de leur choix...

- Concernant ton message de 02 h17 :

- j'ai dû couper le tableau sinon il ne passait pas dans le forum parce que trop gros, donc certains individus n'ont pas l'intégralité de leur choix...

[/quote]

@curulis57 : il n'est pas nécessaire de reproduire ce traitement manuel puisqu'il est déjà pris en compte dans les données que je dois traiter.

A priori il semble qu'il n'y ait pas eu de limitations dans les dictionnaires : la zone la plus demandée est la 908 avec 1382 demandes qu'on retrouve bien dans le dictionnaire "z" des zones et sa taille est de 11011 caractères (environ 3 pages sous word avec les polices courantes)

Je ne pense pas que les doublons de points entrent en jeu car la moulinette les oublie (mon programme prend dans l'ordre des points tel que trié dans excel).

Je vais "tracker" demain ce qui se passe pour quelques individus avec affectations multiples ...

Ouf ! je vais dormir moins c** !

C'était tout bête ... je ne faisais aucun calcul car tout simplement les données étaient numériques et non alpha numériques comme dans mon développement ! Je m'explique : quand j'allais chercher dans le dico les choix d'un individu, il ne trouvait rien car dans le dico c'était en numérique et dans le résultat de l'extraction de tous les candidats pour une zone c'était en texte par construction !!

Après légère modification (ajout de Val) et un nouvel aménagement de l'utilisation dico et array, le temps a même diminué (il a bien fallu que je me creuse encore la cervelle car la recherche des causes prenait trop de temps).

Je suis donc passé maintenant de 7mn à 13 secondes.

J'attends le résultat de curulis pour comparer les affectations.

Merci beaucoup quelle rapidité c'est incroyable !!!!

Bon par contre ça ne fonctionne toujours pas, il y a toujours de nombreux doublons

Alors il y a une différence par rapport au fichier réel, c'est que le numéro d'individu est composé de chiffres et de lettres, peut-être que c'est ça qui met à mal ton programme ? J'ai testé en ajoutant un "a" à chaque individu et effectivement cela met des doublons. Désolé de pas te l'avoir dit, je ne pensais pas que cela serait un problème

Je vois aussi qu'il y a environ 300 lignes dans l'onglet "résultat" où il y a marqué "0" dans la colonne "individu", je ne sais pas ce que ça signifie...

Sur les choix n°1 ou + manquant, ce n'est pas lié qu'au fait que le fichier d'avant été tronqué effectivement, mais c'est parfaitement normal, même si c'est un peu compliqué à expliquer...

Je constate un autre problème sur le fichier sur lequel tu t'es basé : dans les dernières lignes de l'onglet "résultat", il y a des numéros d'individu qui n'existent pas : ils dépassent 66998 alors que c'est le maximum possible.

Rechercher des sujets similaires à "trier tableau vba"