[RESOLU] Tri sur plus d'un champ (List)

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

[RESOLU] Tri sur plus d'un champ (List)

Message par omega »

Bonjour à tous,

Est-il possible de trier une liste chaînée sur 2 champs en même temps ? Exemple sur nom,matricule (tri sur le nom puis sur matricule)
Pour trier sur un champ, le code est le suivant:

Code : Tout sélectionner

SortStructuredList(Maliste(), #PB_Sort_Ascending|#PB_Sort_NoCase, OffsetOf(MalisteStr\nom), #PB_Sort_String)

Merci
Dernière modification par omega le lun. 05/févr./2018 20:05, modifié 1 fois.
Win7 (x64) 64 bits Pb 5.72
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Tri sur plus d'un champ (List)

Message par falsam »

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: Tri sur plus d'un champ (List)

Message par falsam »

Si tu ne souhaites pas utiliser une variable de regroupement alors tu as le tri fusion en natif dans PureBasic depuis la version 4.30.

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\Champs2), #PB_String) ;Produits en premier
SortStructuredList(Tableau(), #PB_Sort_Ascending, OffsetOf(Test\Champs1), #PB_String) ;Famille en dernier 

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
omega
Messages : 626
Inscription : sam. 26/nov./2011 13:04
Localisation : Alger

Re: Tri sur plus d'un champ (List)

Message par omega »

Bonjour Falsam et merci pour ces 2 codes. Le 1er concerne un tableau et non pas une liste chaînée mais bon dans les 2 cas (les 2 exemples de code), il s'agit finalement de regrouper 2 ou 3 champs ensembles. C'est effectivement une solution mais il y a un mais:
Cette solution marche dans le cas où je connais les champs à trier, c'est à dire que le tri concerne toujours 2 champs bien définis et connus, exemple Nom et matricule... Mais quand il s'agit de choisir entre plusieurs champs (une dizaine par exemple, comme c'est mon cas) alors il va falloir modifier le contenu de la clé à chaque fois que l'utilisateur change d'argument de tri. Je m'explique (et dis moi si je ne déconne pas) :

Structure ClientStr
Nom.s
Tel.s
adresse.s
profession.s
age.i
sexe.s
Salaire.q
CleTri.s
EndStructure

Si l'utilisateur choisit le tri suivant: Nom, telephone
Je dois parcourir la liste pour mettre à jour le contenu de la clé comme suit:
CleTri=nom$ + space(1) + Tel$
et je trie sur CleTri

Si l'utilisateur choisit le tri suivant: Sexe,Nom
Je dois parcourir la liste pour mettre à jour le contenu de la clé comme suit:
CleTri=sexe$ + space(1) + nom$
et je trie sur CleTri

etc...

Donc la mise à jour du contenu de la cle se fait à chaque fois que l'utilisateur change d'argument de tri

Est ce que c'est correct Falsam?

Merci beaucoup
Win7 (x64) 64 bits Pb 5.72
Avatar de l’utilisateur
Ar-S
Messages : 9477
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Tri sur plus d'un champ (List)

Message par Ar-S »

Pour ce genre de trie une base sqlite serait surement bien plus adéquate non ? Tu as pas mal d'exemple sur le forum.
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
omega
Messages : 626
Inscription : sam. 26/nov./2011 13:04
Localisation : Alger

Re: Tri sur plus d'un champ (List)

Message par omega »

Non Ar-s, c'est trop lent avec sqlite, même dans ce cas là, il faut retrier la table à chaque fois en fonction des arguments. J'ai déjà essayé et ça prend 100 fois plus de temps qu'une liste chaînée.
Win7 (x64) 64 bits Pb 5.72
Avatar de l’utilisateur
Ar-S
Messages : 9477
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Tri sur plus d'un champ (List)

Message par Ar-S »

OK...
Tu utilises les listes, tu aurais du opter pour les Map et / ou tableau mais bon...
Voilà mon astuce pour rester dans ton optique de codage.

En gros ta clé trie ne sert pas. Tu as ordre pré établie dans ta structure et tu souhaites le trier dans l'ordre que tu veux.. Voilà comment je procèderai.

Code : Tout sélectionner

Structure ClientStr
Nom.s         ; 1
Tel.s         ; 2
adresse.s     ; 3
profession.s  ; 4
age.s         ; 5
sexe.s        ; 6
Salaire.s     ; 7
EndStructure

; La liste qui va stocker les infos structurées
Global NewList TousLesChamps.ClientStr()
; La liste qui va stocker ligne par lignes les infos clients le tout séparé par une virgule
Global NewList Client.s()


Macro AddClient(M_Nom, M_Tel, M_Adresse, M_Prof, M_age, M_Sexe, M_salaire)
  ; Ar-S
 ; On stock tous les champs dans une simple liste structurée
  AddElement (TousLesChamps() )
  TousLesChamps.ClientStr\Nom       = M_Nom
  TousLesChamps\Tel       = M_Tel
  TousLesChamps\adresse   = M_Adresse
  TousLesChamps\profession= M_Prof
  TousLesChamps\age       = M_age
  TousLesChamps\sexe      = M_Sexe
  TousLesChamps\Salaire   = M_salaire

  ; stockage ligne par lignes des infos clients le tout séparé par une virgule
  AddElement( Client() )
  Client() = TousLesChamps\Nom.s +","+TousLesChamps\Tel.s+","+TousLesChamps\Adresse.s +","+ TousLesChamps\profession.s +","+ TousLesChamps\age.s +","+ TousLesChamps\sexe.s +","+ TousLesChamps\Salaire.s
EndMacro

Macro TrieClient(Champ1,Champ2,Champ3,Champ4,Champ5,Champ6,Champ7)
  ;Ar-S
; La macro qui va servir à trier selon le numéro des champs
  ForEach Client()
    Ligne.s = Client()
    El1.s = StringField(Ligne.s,Champ1,",")
    El2.s = StringField(Ligne.s,Champ2,",")
    El3.s = StringField(Ligne.s,Champ3,",")
    El4.s = StringField(Ligne.s,Champ4,",")
    El5.s = StringField(Ligne.s,Champ5,",")
    El6.s = StringField(Ligne.s,Champ6,",")
    El7.s = StringField(Ligne.s,Champ7,",")
    
    ; C'est cette NewLigne.s que tu remplaceras par une nouvelle liste chainée (faut bien que tu bosses un peu)
  NewLigne.s = El1 + Space(1) + El2 + Space(1) + El3 + Space(1) + El4 + Space(1) + El5 + Space(1) + El6 + Space(1) + El7
  Debug NewLigne
  Next

EndMacro

; ///////////////////////////////////////////////////
; /////////////////// PROG //////////////////////////
; ///////////////////////////////////////////////////

; Ajoute client 1
AddClient("Ar-S", "06.06.06.06.06", "Rue du zbouel", "informaticien", "42", "rose", "1400")
; Ajoute client 2
AddClient("Omega", "07.07.07.07.07", "Rue du zboubi", "codeur", "30", "autre", "1800")

; Affichage standard
Debug "/////// Affichage standard //////////"
ForEach Client()
  Debug Client()
Next

Debug ""

Debug "/////// Affichage trié //////////"
;Je trie selon un ordre désiré
TrieClient(1,7,2,3,5,4,6) ; Tri Nom Salaire Tel Adresse Age Prof Sexe


~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Tri sur plus d'un champ (List)

Message par falsam »

omega a écrit :Si l'utilisateur choisit le tri suivant: Nom, telephone
Je dois parcourir la liste pour mettre à jour le contenu de la clé comme suit:
CleTri=nom$ + space(1) + Tel$
et je trie sur CleTri

Si l'utilisateur choisit le tri suivant: Sexe,Nom
Je dois parcourir la liste pour mettre à jour le contenu de la clé comme suit:
CleTri=sexe$ + space(1) + nom$
et je trie sur CleTri

etc...

Donc la mise à jour du contenu de la cle se fait à chaque fois que l'utilisateur change d'argument de tri

Est ce que c'est correct Falsam?
Presque correct ....

Tu dois formater chacune de tes variables dans la variable de regroupement avec la fonction LSet()

Au lieu de

Code : Tout sélectionner

CleTri=nom$ + space(1) + Tel$
utilises à la place

Code : Tout sélectionner

CleTri=LSet(nom$, 40, " ") + LSet(Tel$, 15, " ")
Je pense qu'utiliser une base de données SQLite en mémoire serait plus adéquate pour trier des données.

:idea: Créer une base de données en mémoire

Code : Tout sélectionner

OpenDatabase(#DataBase1, ":memory:", "", "")
si tu sais manipuler une base de données SQLite, tu dois savoir utiliser la clause ORDER dans une sélection de d'enregistrements.

Code : Tout sélectionner

SELECT * FROM MyTable ORDER BY col1,col2,col3 ASC
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
microdevweb
Messages : 1800
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Re: Tri sur plus d'un champ (List)

Message par microdevweb »

Il est également possible de faire un tableau trié contenant les adresses de la liste.

Voici plusieurs méthodes de tri
http://www.purebasic.fr/french/viewtopi ... 21&t=16420
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Avatar de l’utilisateur
omega
Messages : 626
Inscription : sam. 26/nov./2011 13:04
Localisation : Alger

Re: Tri sur plus d'un champ (List)

Message par omega »

Merci à vous tous pour votre aide
@A-rs
Je vais tester ta deuxième proposition et j'y reviendrais
@Falsam
Si tu es sûr qu'une base de données sqlite en mémoire est plus rapide qu'une liste chaînée, j'aimerais bien utiliser cette solution, car j'utilise une base sqlite (sur disque) et j'ai constaté que la relecture d'une table (à chaque nouveau tri) prend beaucoup de temps car il s'agit d'afficher plus de 8000 lignes sur une listIconGadget. Autrement dit, si l'utilisateur change l'argument de tri, ces 8000 lignes doivent être Retriées selon les nouveaux arguments et réaffichées sur ListIconGadget. Si je retrie la table et la réaffiche cela prend énormément de temps par rapport à une liste chainée.
Ma question: Une base en mémoire serait elle plus efficace en matière de temps?
Dernière question: j'utilise très souvent la base sqlite (sur disque) mais jamais en mémoire.
Est ce que ce code suffit pour créer une base en mémoire?

Code : Tout sélectionner

OpenDatabase(#DataBase1, ":memory:", "", "")
Merci beaucoup
Win7 (x64) 64 bits Pb 5.72
Mesa
Messages : 1097
Inscription : mer. 14/sept./2011 16:59

Re: Tri sur plus d'un champ (List)

Message par Mesa »

Tri à bulle multichamps pour list et tableau d'après pappip.

http://www.purebasic.fr/french/viewtopi ... 2&start=30

M.
Avatar de l’utilisateur
omega
Messages : 626
Inscription : sam. 26/nov./2011 13:04
Localisation : Alger

Re: Tri sur plus d'un champ (List)

Message par omega »

Merci à vous tous ! plusieurs méthodes qui marchent ! Il va falloir choisir.
Merci encore et bonne continuation
Win7 (x64) 64 bits Pb 5.72
Répondre