2010-08-14 6 views
2

Je voudrais trier une liste de chaînes représentant des chemins. Le résultat du tri aura un ordre hiérarchique. Ce que je veux dire est: pour chaque chemin de répertoire, je veux lister tous les fichiers dans ce chemin (alphabétiquement ou pas n'importe) dans la première fois. Ensuite, chaque chemin de sous-répertoire sera répertorié. Pour chaque sous-répertoire, je veux tous les fichiers ... et ainsi de suite.Tri des chemins de chaîne dans VB.NET

Voici un exemple:

(Avant)

emule/changelog.txt 
emule/config/ 
emule/config/adresses.dat 
emule/config/nodes.dat 
emule/config/webservices.dat 
emule/eMule.tmpl 
emule/eMule_Chicane.tmpl 
emule/license.txt 
emule/license-GER.txt 
emule/readme.txt 
emule/Skin/ 
emule/Skin/Daan-V2-8.eMuleSkin.ini 
emule/Skin/DaanV2-8/ 
emule/Skin/DaanV2-8/back.ICO 
emule/Skin/DaanV2-8/WebServer.ico 
emule/Template.eMuleSkin.ini 
emule/webserver/ 
emule/webserver/add_server.gif 
emule/webserver/arrow_down.gif 
emule/webserver/arrow_right.gif 
emule/webserver/yellow.gif 
emule/emule.exe 

(Après)

emule/changelog.txt 
emule/emule.exe 
emule/eMule.tmpl 
emule/eMule_Chicane.tmpl 
emule/license.txt 
emule/license-GER.txt 
emule/readme.txt 
emule/Template.eMuleSkin.ini 
emule/config/ 
emule/config/adresses.dat 
emule/config/nodes.dat 
emule/config/webservices.dat 
emule/Skin/ 
emule/Skin/Daan-V2-8.eMuleSkin.ini 
emule/Skin/DaanV2-8/ 
emule/Skin/DaanV2-8/back.ICO 
emule/Skin/DaanV2-8/WebServer.ico 
emule/webserver/ 
emule/webserver/add_server.gif 
emule/webserver/arrow_down.gif 
emule/webserver/arrow_right.gif 
emule/webserver/yellow.gif 

J'ai essayé plusieurs solutions comme Array.Sort() avec une fonction personnalisée IComparable.

Avez-vous une idée? Merci beaucoup.

EDIT: voici ma méthode IComparable

zipEntries.Sort(AddressOf compareZipEntryFilenames) 

Private Function compareZipEntryFilenames(ByVal x As Object, ByVal y As Object) As Integer 
     Dim one As String = CType(x, ZipEntry).FileName 
     Dim two As String = CType(y, ZipEntry).FileName 

     If Path.GetDirectoryName(one) = Path.GetDirectoryName(two) Then 
      Return String.Compare(one, two) 
     Else 
      Select Regex.Matches(one, "/").Count.CompareTo(Regex.Matches(two, "/").Count) 
       Case -1 'one has less/than two; so one then two 
        Return -1 
       Case 1 'one has more/than two; so two then one 
        Return 1 
       Case Else ' = 0, same number of /; so alphabetical sorting 
        Return String.Compare(one, two) 
      End Select 
     End If 
    End Function 
+0

Veuillez publier la méthode IComparable personnalisée que vous avez écrite. Je pense que c'est la bonne approche. –

+0

Il semble que votre fonction devrait fonctionner - cependant, ce n'est pas 'implémentation' IComparable.CompareTo. –

+0

Non. Le problème était, à la dernière étape, après avoir déterminé le niveau d'imbrication, vous devriez comparer les répertoires, pas les noms de fichiers. Vois ma réponse. De plus, vous n'avez pas à implémenter l'interface, il y a d'autres surcharges. – GSerg

Répondre

1

se révèle être aussi simple que:

Private Function compareZipEntryFilenames(ByVal x As ZipEntry, ByVal y As ZipEntry) As Integer 

    Dim res As Integer = String.Compare(Path.GetDirectoryName(x.FileName), Path.GetDirectoryName(y.FileName)) 

    If res = 0 Then 
     Return String.Compare(x.FileName, y.FileName) 
    Else 
     Return res 
    End If 

End Function 
+0

Ouais! Vous êtes génial - vous venez de résoudre mon problème! Merci beaucoup – user420280

+0

BTW il y a une chose que je ne comprends pas. Path.PathSeparator renvoie ";" c - Je pense que vous l'avez utilisé pour compter "/", pas ";". Et ainsi, il n'y a jamais ";" dans les chaînes. – user420280

+0

Ouch. Cela fonctionne seulement parce qu'il a un bug. Et réparer le bug le brise. Génial. Je posterai la version corrigée. – GSerg

0

Insérez le bas dans la classe où le genre se produit, puis utilisez zipEntries.Sort(new PathComparer)

private class PathComparer 
     implements IComparer 

    Public Function compareZipEntryFilenames(ByVal x As Object, ByVal y As Object) As Integer Implements IComparer.Compare 
     Dim one As String = CType(x, ZipEntry).FileName 
     Dim two As String = CType(y, ZipEntry).FileName 

     If Path.GetDirectoryName(one) = Path.GetDirectoryName(two) Then 
      Return String.Compare(one, two) 
     Else 
      Select Regex.Matches(one, "/").Count.CompareTo(Regex.Matches(two, "/").Count) 
       Case -1 'one has less/than two; so one then two 
        Return -1 
       Case 1 'one has more/than two; so two then one 
        Return 1 
       Case Else ' = 0, same number of /; so alphabetical sorting 
        Return String.Compare(one, two) 
      End Select 
     End If 
     End Function  
    end class 
+0

Ceci est une autre façon de lier IComparable à la méthode Sort(). Parce que je ne veux pas ajouter de classe, j'ai décidé de créer une fonction dans ma classe de projet. Le comportement est le même. – user420280

+0

Neat - Je n'ai pas encore rencontré la variante de comparaison (Of T) de Sort! –