[RESOLU] Trier une liste sur 2 arguments numériques

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Avatar de l’utilisateur
omega
Messages : 617
Inscription : sam. 26/nov./2011 13:04
Localisation : Alger

[RESOLU] Trier une liste sur 2 arguments numériques

Message par omega »

Bonsoir,

J'ai une liste que je souhaiterais trier sur 2 champs numériques (codeprod puis datenum)

Code : Tout sélectionner

Structure Tpmp
  Codeprod.i  
  datenum.i
  even.s
  qe.s
  qs.s
  pu.s
EndStructure

SortStructuredList(PmpList(), #PB_Sort_Ascending, OffsetOf(tPmp\Champs de tri),TypeOf(tpmp\Champs de tri))
Merci
Dernière modification par omega le sam. 27/juin/2020 21:58, modifié 1 fois.
Win7 (x64) 64 bits Pb 5.72
Avatar de l’utilisateur
Fig
Messages : 1176
Inscription : jeu. 14/oct./2004 19:48

Re: Trier une liste sur 2 arguments numériques

Message par Fig »

Code : Tout sélectionner

Structure Tpmp
  Codeprod.i 
  datenum.i
  even.s
  qe.s
  qs.s
  pu.s
EndStructure
NewList PmpList.Tpmp()

SortStructuredList(PmpList(), #PB_Sort_Ascending, OffsetOf(tPmp\Codeprod),TypeOf(tpmp\Codeprod))
SortStructuredList(PmpList(), #PB_Sort_Ascending, OffsetOf(tPmp\datenum),TypeOf(tpmp\datenum))
Je ne comprends pas ce qui te pose problème...
Pb utilise un tri "stable" cad en qu'il garde leur ordre précédent pour les éléments égaux.
Selon ce que tu veux obtenir, il suffit d'inverser l'ordre des deux tris.
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 6.00LTS - 64 bits
Avatar de l’utilisateur
omega
Messages : 617
Inscription : sam. 26/nov./2011 13:04
Localisation : Alger

Re: Trier une liste sur 2 arguments numériques

Message par omega »

Bonjour Fig

En fait, ce que je souhaiterais avoir comme ordre est comme suit:

Codeprod Datenum
. 01 01
. 01 02
. 01 03
. 02 01
. 02 02
. 02 03
etc...

Pour chaque CodeProd, je dois traiter toutes les datenum dans l'ordre. En reprenant ton exemple, le 1er tri de la liste peut nous donner :

Codeprod Datenum
. 01 02
. 01 01
. 01 03
. 02 03
. 02 02
. 02 01

Le 2ème tri nous donnera:

Codeprod Datenum
. 01 01
. 02 01
. 01 02
. 02 02
. 02 03
. 01 03

On voit bien que la liste n'est pas ordonnée comme prévu.
Win7 (x64) 64 bits Pb 5.72
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Trier une liste sur 2 arguments numériques

Message par Ollivier »

Ça ne marche pas, ça ?

Code : Tout sélectionner

Structure Les2
   Code.L
   DateN.L
EndStructure

Structure Pump
   StructureUnion
      Les2.Les2
      Tri.Q
   EndStructureUnion
   Autre.S
EndStructure

NewList L.Pump()

; ...

SortStructuredList(L(), #PB_Sort_Ascending, OffsetOf(Pump\Tri), TypeOf(Pump\Tri) )
Avatar de l’utilisateur
Naheulf
Messages : 191
Inscription : dim. 10/mars/2013 22:22
Localisation : France

Re: Trier une liste sur 2 arguments numériques

Message par Naheulf »

Il faut faire les tris dans l’ordre du moins important vers le plus important.

Comme l’avait bien précisé Fig
Fig a écrit :Selon ce que tu veux obtenir, il suffit d'inverser l'ordre des deux tris.
Il te suffit donc de remplacer dans son exemple :

Code : Tout sélectionner

SortStructuredList(PmpList(), #PB_Sort_Ascending, OffsetOf(tPmp\Codeprod),TypeOf(tpmp\Codeprod))
SortStructuredList(PmpList(), #PB_Sort_Ascending, OffsetOf(tPmp\datenum),TypeOf(tpmp\datenum))
par

Code : Tout sélectionner

SortStructuredList(PmpList(), #PB_Sort_Ascending, OffsetOf(tPmp\datenum),TypeOf(tpmp\datenum))
SortStructuredList(PmpList(), #PB_Sort_Ascending, OffsetOf(tPmp\Codeprod),TypeOf(tpmp\Codeprod))
De cette façon, le tri par datenum (effectué du coup en premier) ne servira que de discriminant pour le second tri par Codeprod. Second tri qui apparaîtra alors comme tri principal, car les éléments identiques pour celui-ci se retrouveront côte à côte.
Avatar de l’utilisateur
omega
Messages : 617
Inscription : sam. 26/nov./2011 13:04
Localisation : Alger

Re: Trier une liste sur 2 arguments numériques

Message par omega »

Non, ça n'a pas marché. Je m'en doutais: Le tri en 2 étapes ne marche pas c'est logique car le 2ème tri change forcément l'ordre précédent. Je vais tester le code d'Olivier
Win7 (x64) 64 bits Pb 5.72
Avatar de l’utilisateur
omega
Messages : 617
Inscription : sam. 26/nov./2011 13:04
Localisation : Alger

Re: Trier une liste sur 2 arguments numériques

Message par omega »

Ce qu'il y a lieu de faire, comme je l'ai dit sur mon post, c'est de pouvoir trier sur 2 champs EN MEME TEMPS ! Si c'était une table sqlite, c'est faisable, il suffit de faire comme ça:

Code : Tout sélectionner

sql=select * from matable order by codeProd,Datenum"
Mais sur une liste, je crois qu'il faut simplement créer un champs qui contient les 2 champs l'un à la suite de l'autre, exemple:
Pendant le remplissage de la liste:

Code : Tout sélectionner

 AddElement(MaListe())
  maListe()\Codeprod=codeprod$
  maListe()\datenum=datenum
  maListe()\lib=lib$
  maListe()\rec=rec$
  maListe()\CleTri=Codeprod + space(1) + str(datenum) 
Puis on tri avant l'affichage, comme ça:

Code : Tout sélectionner

SortStructuredList(MaListe(), #PB_Sort_Ascending, OffsetOf(Liste\cletri),TypeOf(Liste\cletri))
Je L'ai essayé et ça a marché! Seulement quand il s'agit de champs numériques, ce n'est pas toujours évident....
Win7 (x64) 64 bits Pb 5.72
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Trier une liste sur 2 arguments numériques

Message par Ollivier »

@omega

en démarrant le sujet avec Codeprod.i, et en changeant ensuite avec codeprod$, on ne peut pas utiliser la même méthode.

StructureUnion fonctionne, en tout cas, normalement. Avant de changer les types de données, il vaut mieux vérifier causes et effets de la méthode avec StructureUnion.

A quoi faut-il se contraindre ?
Quelles sont les conséquences indésirables à apréhender ?

La première contrainte c'est que le type quad 64 bits est impossible à trier avec un autre quad. 64+64 = 128 bits Trop grand !
L'autre contrainte c'est de ne trier que des nombres positifs, donc non signés. Le signe moins du dernier nombre se retrouvant au milieu de la plage de bits, l'état de signe (positif ou négatif) devient un état numérique compris dans le tri. Et malheureusement, c'est le 1 qui a été considéré comme signe négatif, et le zéro comme signe positif. En gros, en matière de signes, les nombres positifs supérieurs aux nombres négatifs sont stockés sous la forme de l'état 0 inférieur à l'état 1 !

Grossière erreur des fabricants de processeurs !!

En tout cas, conséquemment, ça laisse quelques unions de types triables :

Code : Tout sélectionner

A+A+A+A+A+A+A+A (1 cas)
A+A+A+A+A+A+U (7 cas)
L+A+A+A+A (1 cas)
A+A+A+A+U+U (15 cas)
A+A+U+U+U (4 cas)
U+U+U+U (1 cas)
Un quad peut donc servir de tri dans 29 cas combinatoires de variables non signées.

Si on restreind le domaine de définition au nombres positif (entre 0 et 2 milliards), on peut ajouter 5 cas supplémentaires :

Code : Tout sélectionner

A+L+A+A+A
A+A+L+A+A
A+A+A+L+A
A+A+A+A+L
L+L
C'est ce dernier cas que j'ai mis en exemple. Donc ne pas oublier que ça se limite aux nombres entre 0 et 2 milliards.


A ton tour maintenant, d'expliquer les contraintes de tri de chaînes et mélanges de type possibles pour voir que finalement, ton utilisation ultime est plus lente, mais plus simple et plus souple !
Avatar de l’utilisateur
Zorro
Messages : 2185
Inscription : mar. 31/mai/2016 9:06

Re: Trier une liste sur 2 arguments numériques

Message par Zorro »

perso , je serai parti , sur 2 listes !!

vu que tu as 2 elements a trier , comme ça tu trie les deux liste indépendamment

un peux comme ici :
j'utilise 2 listes d'element entrés en désordre dans leur liste respective

puis je trie les 2 listes indépendament l'une de l'autre (le but etant de les mettre en ordre Ascendant(les deux)
puis je t'affiche le resultat ... les deux listes ayant le meme type de tri , pas de probleme
l'avantage de cette methode, c'est que tes 2 listes, tu peut leur accorder un type de tri different l'une de l'autre ....

je t'accorde que c'est tres "scolaire" mais ça a l'avantage de fonctionner :)

Code : Tout sélectionner

Structure list
		codeprod.s
		datenum.s
EndStructure
NewList list1.list()
NewList list2.list()

; on remplis les listes
restore Cdeprd
For i=0 to 8
		Read.c element
		AddElement(List1())
		list1()\codeprod.s=str(element)
Next i
restore Dtenm:
For i=0 to 8
		Read.c element
		AddElement(List2())
		list2()\datenum.s=str(element)
Next i
; les list sont pleines

;on passe  au tri
SortStructuredList(List1(), #PB_Sort_Ascending, OffsetOf(list\Codeprod.s),TypeOf(list\Codeprod.s))
SortStructuredList(List2(), #PB_Sort_Ascending, OffsetOf(list\datenum.s),TypeOf(list\datenum.s))
; c'est trié !

;affichage
ResetList(List1())
ResetList(List2())
ForEach List1()   
		SelectElement( List2(),pos) :   pos=pos+1
		debug list1()\codeprod.s +"  " + list2()\datenum.s
Next

Datasection
		Cdeprd:
		data.c   02,09,03,07,05,06,04,08,01
		Dtenm:
		data.c   01,08,03,07,05,06,04,02,09
EndDataSection
; Epb


ici la meme chose avec une liste numerique et "alphanumerique"

Code : Tout sélectionner


Structure list
		codeprod.b
		datenum.s
EndStructure
NewList list1.list()
NewList list2.list()

; on remplis les listes
restore Cdeprd
For i=0 to 8
		Read.b element.b
		AddElement(List1())
		list1()\codeprod.b=element.b
Next i
restore Dtenm:
For i=0 to 8
		Read.s element2.s
		AddElement(List2())
		list2()\datenum.s=element2.s
Next i
; les lists sont pleines

;on passe  au tri
SortStructuredList(List1(), #PB_Sort_Ascending, OffsetOf(list\Codeprod.b),TypeOf(list\Codeprod.b))
SortStructuredList(List2(), #PB_Sort_Ascending, OffsetOf(list\datenum.s),TypeOf(list\datenum.s))
; c'est trié !

;affichage 
ResetList(List1()) 
ResetList(List2()) 
ForEach List1()	
		SelectElement( List2(),pos) :	pos=pos+1
		debug str(list1()\codeprod.b) +"  " + list2()\datenum.s
Next 


Datasection
		Cdeprd: 
		data.b	02,09,03,07,05,06,04,08,01
		Dtenm:
		data.S	"A","B","F","D","C","E","I","G","H"
EndDataSection
; Epb


Image
Image
Site: http://michel.dobro.free.fr/
Devise :"dis moi ce dont tu as besoin, je t'expliquerai comment t'en passer"
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Trier une liste sur 2 arguments numériques

Message par falsam »

Le tri fusion peut donner un résultat incertain. Ma préférence porte sur la clé composée comme le montre cette exemple.

Code : Tout sélectionner

Structure Test
  Champs1.s
  Champs2.s
  Clef.s
EndStructure

NewList Tableau.Test()

AddElement(Tableau())
With Tableau()
  \Champs1 = "Legumes"
  \Champs2 = "Tomates"
EndWith

AddElement(Tableau())
With Tableau()
  \Champs1 = "Fruits"
  \Champs2 = "Oranges"
EndWith

AddElement(Tableau())
With Tableau()
  \Champs1 = "Fruits"
  \Champs2 = "Abricots"
EndWith

AddElement(Tableau())
With Tableau()
  \Champs1 = "Legumes"
  \Champs2 = "Pommes de terre"
EndWith

AddElement(Tableau())
With Tableau()
  \Champs1 = "Fruits"
  \Champs2 = "Papaye"
EndWith

AddElement(Tableau())
With Tableau()
  \Champs1 = "Legumes"
  \Champs2 = "Courgettes"
EndWith

;Creation des clés de tri
ForEach Tableau()
  With Tableau()
    \Clef = LSet(\Champs1, 30, " ") + LSet(\Champs2, 30, " ")
  EndWith
Next

;Tri par famille et par produit
SortStructuredList(Tableau(), #PB_Sort_Ascending, OffsetOf(Test\Clef), #PB_String)

;Vérification
ForEach Tableau()
  Debug Tableau()\Champs1 + " - " + Tableau()\Champs2
Next
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
Fig
Messages : 1176
Inscription : jeu. 14/oct./2004 19:48

Re: Trier une liste sur 2 arguments numériques

Message par Fig »

Chez moi ça marche très bien...

Comme je l'écrivais plus haut, Pb utilise un tri stable (tri par fusion) pour ses listes donc pas de problème...
https://fr.wikipedia.org/wiki/Algorithm ... Tri_stable
Le mieux c'est d'essayer les codes avant de rejeter une solution. :mrgreen:
Codeprod :0 Datenum :0
Codeprod :0 Datenum :1
Codeprod :0 Datenum :2
Codeprod :0 Datenum :3
Codeprod :1 Datenum :0
Codeprod :1 Datenum :1
Codeprod :1 Datenum :2
Codeprod :1 Datenum :3
Codeprod :2 Datenum :0
Codeprod :2 Datenum :1
Codeprod :2 Datenum :2
Codeprod :2 Datenum :3
Codeprod :3 Datenum :0
Codeprod :3 Datenum :1
Codeprod :3 Datenum :2
Codeprod :3 Datenum :3

Code : Tout sélectionner

Structure Tpmp
  Codeprod.i
  datenum.i
  even.s
  qe.s
  qs.s
  pu.s
EndStructure
NewList PmpList.Tpmp()
;on remplit la liste
For i=0 To 3
  For t=0 To 3
  AddElement(pmplist())
  pmplist()\Codeprod=t
  pmplist()\datenum=i
  Next t
Next i

;on mélange la liste....
ForEach PmpList()
  a.tpmp=PmpList()
  PushListPosition(PmpList())
  SelectElement(PmpList(),Random(ListSize(pmplist())-1))
  b.tpmp=PmpList()
  PmpList()=a
  PopListPosition(PmpList())
  PmpList()=b
Next

Debug "LISTE MELANGEE"
ForEach PmpList()
  Debug " Codeprod :"+pmplist()\Codeprod+" Datenum  :"+pmplist()\datenum
Next
Debug " "

;on trie...
SortStructuredList(PmpList(), #PB_Sort_Ascending, OffsetOf(tPmp\datenum),TypeOf(tpmp\datenum))
SortStructuredList(PmpList(), #PB_Sort_Ascending, OffsetOf(tPmp\Codeprod),TypeOf(tpmp\Codeprod))

;et voila !!
Debug "LISTE TRIEE"
ForEach PmpList()
  Debug " Codeprod :"+pmplist()\Codeprod+" Datenum  :"+pmplist()\datenum
Next
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 6.00LTS - 64 bits
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Trier une liste sur 2 arguments numériques

Message par falsam »

Fig a écrit :Le mieux c'est d'essayer les codes avant de rejeter une solution.
je ne rejette pas le tri fusion. Par contre mal utiliser tu peux te faire avoir.

Exemple avec ce tri par famille de produits

Code : Tout sélectionner

Structure Test
  Champs1.s
  Champs2.s
EndStructure

NewList Tableau.Test()

AddElement(Tableau())
With Tableau()
  \Champs1 = "Legumes"
  \Champs2 = "Tomates"
EndWith

AddElement(Tableau())
With Tableau()
  \Champs1 = "Fruits"
  \Champs2 = "Oranges"
EndWith

AddElement(Tableau())
With Tableau()
  \Champs1 = "Fruits"
  \Champs2 = "Abricots"
EndWith

AddElement(Tableau())
With Tableau()
  \Champs1 = "Legumes"
  \Champs2 = "Pommes de terre"
EndWith

AddElement(Tableau())
With Tableau()
  \Champs1 = "Fruits"
  \Champs2 = "Papaye"
EndWith

AddElement(Tableau())
With Tableau()
  \Champs1 = "Legumes"
  \Champs2 = "Courgettes"
EndWith

;Tri par famille et par produit
SortStructuredList(Tableau(), #PB_Sort_Ascending, OffsetOf(Test\Champs1), #PB_String)
SortStructuredList(Tableau(), #PB_Sort_Ascending, OffsetOf(Test\Champs2), #PB_String)

ForEach Tableau()
  Debug Tableau()\Champs1 + " - " + Tableau()\Champs2
Next
Résultat
Fruits - Abricots
Legumes - Courgettes
Fruits - Oranges
Fruits - Papaye
Legumes - Pommes de terre
Legumes - Tomates
C'est pas vraiment le résultat attendu.

Je n'avais pas compris qu'il fallait d'abord trier sur la clé secondaire puis sur la clé primaire.
Donc remplacer

Code : Tout sélectionner

;Tri par famille et par produit
SortStructuredList(Tableau(), #PB_Sort_Ascending, OffsetOf(Test\Champs1), #PB_String)
SortStructuredList(Tableau(), #PB_Sort_Ascending, OffsetOf(Test\Champs2), #PB_String)
par

Code : Tout sélectionner

;Tri par famille et par produit
;(Trier la clé secondaire d'abord et la clé principale en dernier)
SortStructuredList(Tableau(), #PB_Sort_Ascending, OffsetOf(Test\Champs2), #PB_String)
SortStructuredList(Tableau(), #PB_Sort_Ascending, OffsetOf(Test\Champs1), #PB_String)
Au passage merci à Demivec pour cette précision.
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Trier une liste sur 2 arguments numériques

Message par falsam »

En 2018 Omega avait posé la même question de tri de liste :wink:
https://www.purebasic.fr/french/viewtop ... =1&t=17127
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
Fig
Messages : 1176
Inscription : jeu. 14/oct./2004 19:48

Re: Trier une liste sur 2 arguments numériques

Message par Fig »

Désolé, je m'adressais à Omega...
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 6.00LTS - 64 bits
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Trier une liste sur 2 arguments numériques

Message par Ollivier »

Ollivier a écrit :A ton tour maintenant, d'expliquer les contraintes de tri de chaînes et mélanges de type possibles pour voir que finalement, ton utilisation ultime est plus lente, mais plus simple et plus souple !
@omega

Bon ben finalement, ton utilisation ultime est plus lente, moins simple et
Répondre