Remove duplicate elements

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Geo Trouvpatou
Messages : 471
Inscription : dim. 23/déc./2007 18:10

Remove duplicate elements

Message par Geo Trouvpatou »

Salut.

Je scanne mes dossiers et sous-dossiers pour en obtenir le contenu.
Ensuite je ne conserve que le chemin du fichier qui me permettra par la suite de re-créer les dossiers et sous-dossiers avant un dépackage.

Mais si j'ai 5 fichiers dans un dossier, je vais avoir 5 fois ce chemin par exemple :
Dossier1/Dossier2/Dossier2/

Donc je devais supprimer les doublons.

Après avoir pas mal galéré, j"ai trouvé ce code qui fonctionne, même si j'imagine que les "Map", n'ont pas été faites pour ça :wink:
Code trouvé ici : http://rosettacode.org/wiki/Remove_dupl ... #PureBasic

Code : Tout sélectionner

EnableExplicit

Structure sPath
      Path$
EndStructure

Debug "========== AVANT SUPPRESSION DES DOUBLONS"
Debug "=========="

; Cette liste chaînée ne sert qu'a voir un exemple des doublons que l'on peut avoir
NewList Chemin.sPath()

AddElement(Chemin()) : Chemin()\Path$ = "dossier1/dossierTruc/dossierMachin/Bidule/"
AddElement(Chemin()) : Chemin()\Path$ = "dossier1/dossierTruc/dossierMachin/" ; Doublon
AddElement(Chemin()) : Chemin()\Path$ = "dossier2/dossierTruc/dossierMachin/"
AddElement(Chemin()) : Chemin()\Path$ = "dossier1/dossierTruc/dossierDifferent/"
AddElement(Chemin()) : Chemin()\Path$ = "dossier4/dossierTruc/dossierMachin/"
AddElement(Chemin()) : Chemin()\Path$ = "dossier1/dossierTruc/dossierMachin/" ; Doublon
AddElement(Chemin()) : Chemin()\Path$ = "dossier1/dossierTruc/dossierMachin/" ; Doublon
AddElement(Chemin()) : Chemin()\Path$ = "dossier1/dossierTruc/dossierMachin/" ; Doublon
AddElement(Chemin()) : Chemin()\Path$ = "dossier7/dossierTruc/dossierMachin/"
AddElement(Chemin()) : Chemin()\Path$ = "dossier1/dossierSecret/dossierMachin/"

; Trie la liste en fonction du champ 'Path$'qui est une chaîne de caractères (String)
; Le trie ici, ne sert qu'à mieux voir les doublons.
SortStructuredList(Chemin(), #PB_Sort_Ascending, OffsetOf(sPath\Path$), #PB_Sort_String)

ForEach Chemin()
      Debug Chemin()\Path$
Next

Debug "=========="
Debug "========== APRES SUPPRESSION DES DOUBLONS"
Debug "=========="

; Code trouvé ici : http://rosettacode.org/wiki/Remove_duplicate_elements#PureBasic
NewMap MyElements$()

MyElements$("dossier1/dossierTruc/dossierMachin/Bidule/") = "dossier1/dossierTruc/dossierMachin/Bidule/"
MyElements$("dossier1/dossierTruc/dossierMachin/") = "dossier1/dossierTruc/dossierMachin/"
MyElements$("dossier2/dossierTruc/dossierMachin/") = "dossier2/dossierTruc/dossierMachin/"
MyElements$("dossier1/dossierTruc/dossierDifferent/") = "dossier1/dossierTruc/dossierDifferent/"
MyElements$("dossier4/dossierTruc/dossierMachin/") = "dossier4/dossierTruc/dossierMachin/"
MyElements$("dossier1/dossierTruc/dossierMachin/") = "dossier1/dossierTruc/dossierMachin/"
MyElements$("dossier1/dossierTruc/dossierMachin/") = "dossier1/dossierTruc/dossierMachin/"
MyElements$("dossier1/dossierTruc/dossierMachin/") = "dossier1/dossierTruc/dossierMachin/"
MyElements$("dossier7/dossierTruc/dossierMachin/") = "dossier7/dossierTruc/dossierMachin/"
MyElements$("dossier1/dossierSecret/dossierMachin/") = "dossier1/dossierSecret/dossierMachin/"

ForEach MyElements$()
      Debug MyElements$()
Next
Bye.
Avatar de l’utilisateur
GeBonet
Messages : 453
Inscription : ven. 29/févr./2008 16:17
Localisation : Belgique

Re: Remove duplicate elements

Message par GeBonet »

Bien vu... Tant que ça marche, hein :D

Maintenant, si par exemple l'objet est de supprimer les doublons sur disque...

- On constitue une liste avec tout les fichiers
- Simultanément une avec ton système.

- A la fin on "déduit" ta liste (ou il n'y a pas de double elle) de la liste complète et il reste la liste des doublons.... A effacer ? (A consommer avec modération.) :wink:
Windows 7 et Windows 8.1 Pb 5.0 jusque 5.24 Lts 64 et 5.3 (64)/b]
“Ceux qui rêvent éveillés ont conscience de mille choses qui échappent à ceux qui ne rêvent qu’endormis.”
-Edgar Allan Poe-
Guimauve
Messages : 1015
Inscription : mer. 11/févr./2004 0:32
Localisation : Québec, Canada

Re: Remove duplicate elements

Message par Guimauve »

Bonjour à tous,

Oui une map peut être utilisée pour ce genre de chose. Cependant, j'ai une préférence pour une structure en Arbre binaire comme ceci :

Code : Tout sélectionner

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Nom du projet : Nom du projet
; Nom du fichier : *.pb
; Version du fichier : 0.0.0
; Programmation : En cours
; Programmé par : Guimauve
; Date : 11-09-2011
; Mise à jour : 11-09-2011
; Code PureBasic : 4.50
; Plateforme : Windows, Linux, MacOS X
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Enumeration 
  
  #NOEUD_ENFANT_GAUCHE
  #NOEUD_ENFANT_DROITE
  #NOEUD_ENFANT_MAX
  
EndEnumeration

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Déclaration de la Structure <<<<<

Structure Noeud

  Mots.s
  Compteur.l
  Enfant.i[#NOEUD_ENFANT_MAX]

EndStructure

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Les observateurs <<<<<

Macro GetNoeudMots(NoeudA)

  NoeudA\Mots

EndMacro

Macro GetNoeudCompteur(NoeudA)

  NoeudA\Compteur

EndMacro

Macro GetNoeudEnfant(NoeudA, EnfantID)

  NoeudA\Enfant[EnfantID]

EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Les mutateurs <<<<<

Macro SetNoeudMots(NoeudA, P_Mots)

  GetNoeudMots(NoeudA) = P_Mots

EndMacro

Macro SetNoeudCompteur(NoeudA, P_Compteur)

  GetNoeudCompteur(NoeudA) = P_Compteur

EndMacro

Macro SetNoeudEnfant(NoeudA, EnfantID, P_Enfant)

  GetNoeudEnfant(NoeudA, EnfantID) = P_Enfant

EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< L'opérateur Reset <<<<<

Macro ResetNoeud(NoeudA)
  
  Debug "ResetNoeud appelé pour le mot : " + GetNoeudMots(NoeudA)
  
  SetNoeudMots(NoeudA, "")
  SetNoeudCompteur(NoeudA, 0)
  
  For EnfantID = 0 To #NOEUD_ENFANT_MAX - 1
    
    If GetNoeudEnfant(NoeudA, EnfantID) <> #Null
      FreeMemory(GetNoeudEnfant(NoeudA, EnfantID))
      SetNoeudEnfant(NoeudA, EnfantID, 0)
    EndIf 
    
  Next

EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< L'opérateur Private_AfficheNoeud <<<<<

Procedure Private_AfficheNoeud(*NoeudA.Noeud)
  
  If *NoeudA <> #Null
      
    Private_AfficheNoeud(GetNoeudEnfant(*NoeudA, #NOEUD_ENFANT_GAUCHE))
    
    Debug GetNoeudMots(*NoeudA) + " =---> " + Str(GetNoeudCompteur(*NoeudA)) + " fois"
    
    Private_AfficheNoeud(GetNoeudEnfant(*NoeudA, #NOEUD_ENFANT_DROITE))
    
  EndIf
  
EndProcedure

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< L'opérateur Private_ResetNoeud <<<<<

Procedure Private_ResetNoeud(*NoeudA.Noeud)
  
  If *NoeudA <> #Null

    For EnfantID = 0 To #NOEUD_ENFANT_MAX - 1
      Private_ResetNoeud(GetNoeudEnfant(*NoeudA, EnfantID))
    Next
   
    ResetNoeud(*NoeudA)

  EndIf
  
EndProcedure

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Déclaration de la Structure <<<<<

Structure ArbreBinaire

  QteNoeud.l
  Noeud.Noeud

EndStructure

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Les observateurs <<<<<

Macro GetArbreBinaireQteNoeud(ArbreBinaireA)

  ArbreBinaireA\QteNoeud

EndMacro

Macro GetArbreBinaireNoeud(ArbreBinaireA)

  ArbreBinaireA\Noeud

EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Les mutateurs <<<<<

Macro SetArbreBinaireQteNoeud(ArbreBinaireA, P_QteNoeud)

  GetArbreBinaireQteNoeud(ArbreBinaireA) = P_QteNoeud

EndMacro

Macro SetArbreBinaireNoeud(ArbreBinaireA, P_Noeud)

  GetArbreBinaireNoeud(ArbreBinaireA) = P_Noeud

EndMacro

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< L'opérateur Reset <<<<<

Macro ResetArbreBinaire(ArbreBinaireA)
  
  SetArbreBinaireQteNoeud(ArbreBinaireA, 0)
  Private_ResetNoeud(GetArbreBinaireNoeud(ArbreBinaireA))

EndMacro

Procedure AfficheArbreBinaire(*Arbre.ArbreBinaire)
  
  Private_AfficheNoeud(GetArbreBinaireNoeud(*Arbre))
  
EndProcedure

Procedure Private_AjouterNoeudArbre(*Arbre.ArbreBinaire, *NoeudA.Noeud, Mot.s)
  
  If GetArbreBinaireQteNoeud(*Arbre) = 0 
    
    SetArbreBinaireQteNoeud(*Arbre, GetArbreBinaireQteNoeud(*Arbre) + 1)
    SetNoeudMots(*NoeudA, Mot)
    SetNoeudCompteur(*NoeudA, 1)
    
    For EnfantID = 0 To #NOEUD_ENFANT_MAX - 1
      SetNoeudEnfant(*NoeudA, EnfantID, #Null)
    Next
    
  Else 
    
    If *NoeudA = #Null
      
      *NoeudA = AllocateMemory(SizeOf(Noeud))
      
      If *NoeudA
        
        SetArbreBinaireQteNoeud(*Arbre, GetArbreBinaireQteNoeud(*Arbre) + 1)
        SetNoeudMots(*NoeudA, Mot)
        SetNoeudCompteur(*NoeudA, 1)
        
        For EnfantID = 0 To #NOEUD_ENFANT_MAX - 1
          SetNoeudEnfant(*NoeudA, EnfantID, #Null)
        Next
        
      Else
        
        MessageRequester("Erreur","Impossible d'allouer de la mémoire !",0)
        End
        
      EndIf
      
    ElseIf UCase(Mot) = UCase(GetNoeudMots(*NoeudA))
      
      SetNoeudCompteur(*NoeudA, GetNoeudCompteur(*NoeudA) + 1)
      
    ElseIf UCase(Mot) < UCase(GetNoeudMots(*NoeudA))
      
      SetNoeudEnfant(*NoeudA, #NOEUD_ENFANT_GAUCHE, Private_AjouterNoeudArbre(*Arbre, GetNoeudEnfant(*NoeudA, #NOEUD_ENFANT_GAUCHE), Mot))
      
    Else
      
      SetNoeudEnfant(*NoeudA, #NOEUD_ENFANT_DROITE, Private_AjouterNoeudArbre(*Arbre, GetNoeudEnfant(*NoeudA, #NOEUD_ENFANT_DROITE), Mot))
      
    EndIf
    
  EndIf
  
  ProcedureReturn *NoeudA
EndProcedure

Procedure AjouterNoeudArbre(*Arbre.ArbreBinaire, Mot.s)
  
  Private_AjouterNoeudArbre(*Arbre, GetArbreBinaireNoeud(*Arbre), Mot)
  
EndProcedure

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< !!! ATTENTION - CODE D'ESSAI !!! <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Dim MyHeros.s(14)

MyHeros(00) = "Zoro"
MyHeros(01) = "Fred"
MyHeros(02) = "Yoda"
MyHeros(03) = "Freak"
MyHeros(04) = "Morpheus"
MyHeros(05) = "Fred"
MyHeros(06) = "Freak"
MyHeros(07) = "Zoro"
MyHeros(08) = "Hercule"
MyHeros(09) = "Yoda"
MyHeros(10) = "Luke"
MyHeros(11) = "Anakin"
MyHeros(12) = "Mace Windu"
MyHeros(13) = "Yoda"
MyHeros(14) = "Obiwan"

Separator.s = LSet("; ", 40, "<")

Debug Separator
Debug "; 1er arbre binaire"

For Index = 0 To 14
  AjouterNoeudArbre(MonArbre01.ArbreBinaire, MyHeros(Index))
Next 

Debug "; Nombre de noeud : " + Str(GetArbreBinaireQteNoeud(MonArbre01))
Debug Separator

AfficheArbreBinaire(MonArbre01)

Debug Separator
Debug "; Reset de l'arbre ! (Libération des noeuds)"
Debug Separator

ResetArbreBinaire(MonArbre01)

; <<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< FIN DU FICHIER <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<
Dans cet exemple lorsque un doublon est inséré dans l'arbre, on incrémente une valeur mais il est très facile de rien faire dans ce cas de figure.

A+
Guimauve

P.S. Je pense que ce code est une version modifié d'un code donné par Comtois.
Geo Trouvpatou
Messages : 471
Inscription : dim. 23/déc./2007 18:10

Re: Remove duplicate elements

Message par Geo Trouvpatou »

Je met ton code dans ma besace, parce que le code que j'ai mis ne fonctionnera peut-être pas dans certains cas de figure, mais tu penses bien que je vais utiliser le mien parce qu'au moins je le comprends :wink:.
Guimauve
Messages : 1015
Inscription : mer. 11/févr./2004 0:32
Localisation : Québec, Canada

Re: Remove duplicate elements

Message par Guimauve »

Geo Trouvpatou a écrit :Je met ton code dans ma besace, parce que le code que j'ai mis ne fonctionnera peut-être pas dans certains cas de figure, mais tu penses bien que je vais utiliser le mien parce qu'au moins je le comprends :wink:.
C'est juste une méthode différente de faire la même chose. Moi j'aime bien avoir plus d'une solution pour faire la même chose. Ceci étant dit, dans ton cas je pense que tu peux utiliser directement une Map au lieu d'une List afin d'éviter d'avoir 2 structures de données différentes pour stocker la même information.

A+
Guimauve
Geo Trouvpatou
Messages : 471
Inscription : dim. 23/déc./2007 18:10

Re: Remove duplicate elements

Message par Geo Trouvpatou »

La newList comme le tri, comme j'ai indiqué dans mon code c'était juste pour avoir un visuel des doublons.
Moi j'aime bien avoir plus d'une solution pour faire la même chose.
Et c'est bien pour ça que j'ai récupéré ton code parce que comme j'ai dit, si un jour je tombais sur un cas de figure où ma solution simplette ne fonctionnait pas, j'espère que ton/votre (si Comtois est impliqué aussi :wink:) code fonctionnera.
Et il aura intérêt sinon je viendrais t'engueuler :mrgreen:.
Guimauve
Messages : 1015
Inscription : mer. 11/févr./2004 0:32
Localisation : Québec, Canada

Re: Remove duplicate elements

Message par Guimauve »

Geo Trouvpatou a écrit :La newList comme le tri, comme j'ai indiqué dans mon code c'était juste pour avoir un visuel des doublons.
Oups, fait exactement comme si c'était pas moi.

A+
Guimauve
dayvid
Messages : 1242
Inscription : mer. 11/nov./2009 18:17
Localisation : Poitiers (Vienne)

Re: Remove duplicate elements

Message par dayvid »

bonjour Guimauve !

J'aime beaucoup ta façon de coder, c'est beau et c'est très propre :)
La vie, C'est comme, Une boitte, De startis, On en voie, De toutes, Les couleurs !

Mon forum http://purebasic.forumphp3.com/index.php
Geo Trouvpatou
Messages : 471
Inscription : dim. 23/déc./2007 18:10

Re: Remove duplicate elements

Message par Geo Trouvpatou »

Grace à la trad de GeBonet, voici une autre technique avec PushListPosition/PopListPosition

Code : Tout sélectionner

EnableExplicit

Structure sPath
      Path$
EndStructure
Global valeur$

Debug "========== AVANT SUPPRESSION DES DOUBLONS"
Debug "=========="

; Cette liste chaînée ne sert qu'a voir un exemple des doublons que l'on peut avoir
NewList Chemin.sPath()

AddElement(Chemin()) : Chemin()\Path$ = "dossier1/dossierTruc/dossierMachin/Bidule/"
AddElement(Chemin()) : Chemin()\Path$ = "dossier1/dossierTruc/dossierMachin/" ; Doublon
AddElement(Chemin()) : Chemin()\Path$ = "dossier2/dossierTruc/dossierMachin/"
AddElement(Chemin()) : Chemin()\Path$ = "dossier1/dossierTruc/dossierDifferent/"
AddElement(Chemin()) : Chemin()\Path$ = "dossier4/dossierTruc/dossierMachin/"
AddElement(Chemin()) : Chemin()\Path$ = "dossier1/dossierTruc/dossierMachin/" ; Doublon
AddElement(Chemin()) : Chemin()\Path$ = "dossier1/dossierTruc/dossierMachin/" ; Doublon
AddElement(Chemin()) : Chemin()\Path$ = "dossier1/dossierTruc/dossierMachin/" ; Doublon
AddElement(Chemin()) : Chemin()\Path$ = "dossier7/dossierTruc/dossierMachin/"
AddElement(Chemin()) : Chemin()\Path$ = "dossier1/dossierSecret/dossierMachin/"

; Trie la liste en fonction du champ 'Path$'qui est une chaîne de caractères (String)
; Le trie ici, ne sert qu'à mieux voir les doublons.
SortStructuredList(Chemin(), #PB_Sort_Ascending, OffsetOf(sPath\Path$), #PB_Sort_String)

ForEach Chemin()
      Debug Chemin()\Path$
Next

Debug "=========="
Debug "========== APRES SUPPRESSION DES DOUBLONS AVEC UNE MAP"
Debug "=========="

; Code trouvé ici : http://rosettacode.org/wiki/Remove_duplicate_elements#PureBasic
NewMap MyElements$()

MyElements$("dossier1/dossierTruc/dossierMachin/Bidule/") = "dossier1/dossierTruc/dossierMachin/Bidule/"
MyElements$("dossier1/dossierTruc/dossierMachin/") = "dossier1/dossierTruc/dossierMachin/"
MyElements$("dossier2/dossierTruc/dossierMachin/") = "dossier2/dossierTruc/dossierMachin/"
MyElements$("dossier1/dossierTruc/dossierDifferent/") = "dossier1/dossierTruc/dossierDifferent/"
MyElements$("dossier4/dossierTruc/dossierMachin/") = "dossier4/dossierTruc/dossierMachin/"
MyElements$("dossier1/dossierTruc/dossierMachin/") = "dossier1/dossierTruc/dossierMachin/"
MyElements$("dossier1/dossierTruc/dossierMachin/") = "dossier1/dossierTruc/dossierMachin/"
MyElements$("dossier1/dossierTruc/dossierMachin/") = "dossier1/dossierTruc/dossierMachin/"
MyElements$("dossier7/dossierTruc/dossierMachin/") = "dossier7/dossierTruc/dossierMachin/"
MyElements$("dossier1/dossierSecret/dossierMachin/") = "dossier1/dossierSecret/dossierMachin/"

ForEach MyElements$()
      Debug MyElements$()
Next



Debug "=========="
Debug "========== APRES SUPPRESSION DES DOUBLONS AVEC PushListPosition/PopListPosition"
Debug "=========="
;
; Elimination d'une valeur en double par un boucle imbriquée. 
;
ForEach Chemin()
      valeur$ = Chemin()\Path$
      PushListPosition(Chemin())
      While NextElement(Chemin())
            If Chemin()\Path$ = valeur$ 
                  DeleteElement(Chemin())
            EndIf
      Wend
      PopListPosition(Chemin())
Next

ForEach Chemin()
      Debug Chemin()\Path$
Next
Répondre