[Résolu] Tri croissant decroissant sur 2 colonnes d'un table

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Avatar de l’utilisateur
Ganagyre
Messages : 67
Inscription : jeu. 09/nov./2006 13:41
Localisation : PACA

[Résolu] Tri croissant decroissant sur 2 colonnes d'un table

Message par Ganagyre »

Bonjour.

Avec la procedure suivante, un tri croissant ou décroissant s'opére sur un des elements (colonne) d'un tableau, contenant des valeurs numeriques.

Code : Tout sélectionner


Procedure Trie(offset,Sens)

  NewList TriTab.Tab()
  For nn=1 To Numeros
    AddElement(TriTab())
    TriTab()\ElementN1 = Tableau(1,nn)
    TriTab()\ElementN2 = Tableau(2,nn)
    TriTab()\ElementN3 = Tableau(3,nn)
  Next

  SortStructuredList(TriTab(), Sens, offset, #PB_Sort_Long)
  nn=1
  ForEach TriTab()
    Tableau(1,nn) =  TriTab()\ElementN1
    Tableau(2,nn) =  TriTab()\ElementN2
    Tableau(3,nn) =  TriTab()\ElementN3
    nn+1
  Next

EndProcedure

;Tri sur le 3 élement/Ordre decroissant

Trie(OffsetOf(Tab\ElementN3),1)


Comment ajouter une option de tri sur un autre element, style

Tri décroissant sur la "colonne 3 " en gardant un ordre croissant des valeurs sur la " colonne 1.

10;10;25
35;10;25
99;10;25
01;10;35
09;10;35
...

Un peu comme les option Tri ou filtre possible sur Excel.

Merci à tous .
Dernière modification par Ganagyre le mer. 29/avr./2009 12:18, modifié 1 fois.
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

en lançant deux tris successivement ? ça ne marche qu'avec le tri des listes chainées. Voir la réponse de Freak dans ce post

http://www.purebasic.fr/english/viewtopic.php?t=35857
Since PB 4.30, SortStructuredList (and SortList) use Mergesort which is a stable sort, so if you first sort all the list by titles and then again by album you will get a list which is sorted by album and each album is sorted by title.

Note that this does not work with Arrays, as SortArray uses Quicksort which is unstable. (ie the sorting of the secondary key would be lost)
Je ne l'ai jamais testé, tu nous diras ce que ça donne :)
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Avatar de l’utilisateur
Ganagyre
Messages : 67
Inscription : jeu. 09/nov./2006 13:41
Localisation : PACA

Message par Ganagyre »

Merci comtois pour ce lien interressant.

Entre temps, en parcourant le forum, j'ai pu y trouver de bonnes idées .
(j'etudie encore certains codes)

Pour obtenir un TRI Croissant Colonne 1 et Decroissant colonne 2, une 3 ieme colonne avec une petite formule .
Ensuite TRI Decroissant sur la colonne 3 donne le bon ordre pour la 1 et 2.

Hum,sauf que maintenant , je "bug" sur la sauvegarde du fichier qui reste vide !

Code : Tout sélectionner

;<<<<<<<<<<<<__VARIABLES__>>>>>>>>>>>>>>>>>>>>>>>
tri.b = 1   ; Tri / 0=Croissant / 1=Decroissant    
JEUX.l = 100 
a.l
b.l = 50
n.l
z.l :j.l
Structure Match
    Equipe.l
    Points.l
    Classement.d
EndStructure

Dim FOOT.Match(JEUX)

Global Dim Tableau.l(3,JEUX) ;(colonnes,Lignes)
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;========== Boucle Remplissage données
For a = 1 To JEUX
    ;----------------EQUIPE / Par Ordre Croissant
    FOOT(a)\Equipe=a
    ;----------------POINTS 
    FOOT(a)\Points=Random(b)+1 
    ;----------------CLASSEMMENT / Sans Doublons   
    FOOT(a)\Classement=FOOT(a)\Points-FOOT(a)\Equipe/100000000000
Next 
;========== Fin Boucle 

Procedure Sauve(File.s) 
  CreateFile(1,File) 
    For n=1 To JEUX 
      WriteStringN(1,Str(Tableau(1,n))+";"+Str(Tableau(2,n))+";"+Str(Tableau(3,n)))
      ;
    Next 
  CloseFile(1) 
EndProcedure  

;------------ Triage Decroissant Du Classement -----      
SortStructuredArray (FOOT(),Tri, OffsetOf (Match\Classement), #PB_Sort_Double )
;---------------------------------------------------     
;
;------------ Remplissage Tableau ------------------      
 For z = 1 To JEUX 
    Tableau(1,z) =  FOOT(z)\Equipe
    Tableau(2,z) =  FOOT(z)\Points 
    Tableau(3,z) =  FOOT(z)\Classement  
 Next 
 ;----------- Fin Remplissage Tableau     
 
;========== Sauvegarde TABLEAU      
Sauve("d:\A_Structure Sauve 1000.txt")
;========== 
;____________Verification Si Triage Fonctionne ____     
OpenConsole () 

 For j =0 To JEUX
    PrintN ( "Equipe =  " + Str (FOOT(j)\Equipe)+ " Points = " + Str (FOOT(j)\Points)+ " Classement = " + Str (FOOT(j)\Classement))
 Next 
 
Input ()
CloseConsole ()

Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

Tu as oublié de rendre globale ta variable Jeux, ou de la partager dans ta procedure sauve() avec Shared.
zaphod
Messages : 135
Inscription : dim. 07/déc./2008 9:32

Message par zaphod »

Faut peut être mettre la variable jeux en global ?
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message par Le Soldat Inconnu »

j'ai cette méthode de tri qui traine aussi
elle peut permettre de mixer les types de données à trier (string et long par exemple), a vous d'adapter le code

Code : Tout sélectionner

; Auteur : Le Soldat Inconnu
; Version de PB : 4
; 
; Explication du programme :
; Tri d'une liste chainée composé d'une structure d'abord sur l'élément a de la liste puis sur l'élément c

; On crée une liste chainé avec des valeurs aléatoires
Structure Tableau_Info
  a.l
  b.l
  c.l
EndStructure
NewList Tableau.Tableau_Info()

For n = 1 To 20
  AddElement(Tableau())
  Tableau()\a = Random(10)
  Tableau()\b = Random(20)
  Tableau()\c = Random(30)
Next

;- Procédé

; On tri d'abord sur "a"
SortStructuredList(Tableau(), 0, OffsetOf(Tableau_Info\a), #PB_Sort_Long)

  ; Puis sur "c"
Tri = -1 ; Mettre ici une valeur qui n'existe pas
Compteur = 0
Depart = -1
ForEach Tableau()
  If Tri = Tableau()\a ; On compte le nombre d'élément à la suite qui ont "a" égaux
    If Depart < 0
      Depart = ListIndex(Tableau()) - 1
    EndIf
    Compteur + 1
  Else ; Puis on trie cette liste d'élément sur "c"
    If Compteur
      SortStructuredList(Tableau(), 0, OffsetOf(Tableau_Info\c), #PB_Sort_Long, Depart, Depart + Compteur)
      SelectElement(Tableau(), Depart + Compteur + 1)
    EndIf
    Compteur = 0
    Depart = -1
    Tri = Tableau()\a ; On copie la nouvelle valeur pour trouvé la prochaine suite d'élément avec "a" égaux
  EndIf
Next
If Compteur ; Si on finis la liste chainée avec une série d'élément "a" égaux
  SortStructuredList(Tableau(), 0, OffsetOf(Tableau_Info\c), #PB_Sort_Long, Depart, Depart + Compteur)
EndIf

; On affiche le résultat
ForEach Tableau()
  Debug Str(Tableau()\a) + " ; " + Str(Tableau()\b) + " ; " + Str(Tableau()\c)
Next


;- Test de rapidité

ClearList(Tableau())
For n = 1 To 50000
  AddElement(Tableau())
  Tableau()\a = Random(10)
  Tableau()\b = Random(20)
  Tableau()\c = Random(50)
Next

Temps1 = ElapsedMilliseconds()

; On tri d'abord sur "a"
SortStructuredList(Tableau(), 0, OffsetOf(Tableau_Info\a), #PB_Sort_Long)

  ; Puis sur "c"
Tri = -1 ; Mettre ici une valeur qui n'existe pas
Compteur = 0
Depart = -1
ForEach Tableau()
  If Tri = Tableau()\a ; On compte le nombre d'élément à la suite qui ont "a" égaux
    If Depart < 0
      Depart = ListIndex(Tableau()) - 1
    EndIf
    Compteur + 1
  Else ; Puis on trie cette liste d'élément sur "c"
    If Compteur
      SortStructuredList(Tableau(), 0, OffsetOf(Tableau_Info\c), #PB_Sort_Long, Depart, Depart + Compteur)
      SelectElement(Tableau(), Depart + Compteur + 1)
    EndIf
    Compteur = 0
    Depart = -1
    Tri = Tableau()\a ; On copie la nouvelle valeur pour trouvé la prochaine suite d'élément avec "a" égaux
  EndIf
Next
If Compteur ; Si on finis la liste chainée avec une série d'élément "a" égaux
  SortStructuredList(Tableau(), 0, OffsetOf(Tableau_Info\c), #PB_Sort_Long, Depart, Depart + Compteur)
EndIf

Temps2 = ElapsedMilliseconds()

; On affiche le résultat
MessageRequester("Tri", Str(Temps2 - Temps1) + "ms")
une autre méthode un peu plus bête pour trier sur plusieurs éléments d'un tableau.
Elle peut-être un peu moins rapide mais elle fonctionne avec tout les types de variables et elle est facile à faire

l'astuce consiste à ajouter un champ "Tri" dans la structure du tableau

Code : Tout sélectionner

; Auteur : Le Soldat Inconnu
; Version de PB : 4
; 
; Explication du programme :
; Trier un tableau avec structure sur plusieurs critères

Structure Valeur
  a.s
  b.l
  c.f
  Tri.s
EndStructure

Global NewList Tableau.Valeur()

; Remplissage aléatoire
For n = 1 To 20
  AddElement(Tableau())
  Tableau()\a = Chr(Random(25) + 65)
  Tableau()\b = Random(9)
  Tableau()\c = Random(20) / 10
Next

; On veut trier d'abord sur "c" puis sur "a et enfin sur "b"
ForEach Tableau()
  Tableau()\Tri = StrF(Tableau()\c) + Tableau()\a + Str(Tableau()\b)
Next

; on trie
SortStructuredList(Tableau(), #PB_Sort_Ascending, OffsetOf(Valeur\Tri), #PB_Sort_String)

; on affiche
ForEach Tableau()
  Debug Tableau()\a + " , " + Str(Tableau()\b) + " , " + StrF(Tableau()\c)
Next
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Avatar de l’utilisateur
Ganagyre
Messages : 67
Inscription : jeu. 09/nov./2006 13:41
Localisation : PACA

Message par Ganagyre »

Merci à vous, djes, zaphod , Le Soldat Inconnu.

L'affectation Global qui manquait en effet à une variable !
(punaise ce que j'ai pu chercher ou était le truc qui clochait) .

Le Soldat Inconnu, trés instructif les 2 méthodes de tri, il y a de quoi adapter selon les besoins en effet.


:D
Répondre