none
trier une liste de chaines RRS feed

  • Question

  • Bonjour

    Peut-on à la fois trier une liste de mots en fonction de leur taille puis en ordre alphabétique :

    chat

    chien

    belette

    giraffe

    lapinou

    Que rajouter au code suivant ?

    Array.Sort(Words, AddressOf CompareByLength)
    Private Shared Function CompareByLength( _
         ByVal x As String, ByVal y As String) As Integer
        Return x.Length.CompareTo(y.Length)
      End Function
    
    merci

     

     


    Cordialement
    Pascal
    http://www.scalpa.info
    mercredi 20 juillet 2011 16:32

Réponses

  • Bonjour,

    Ceci devrait faire l'affaire, mais il faudra peut-être affiner la comparaison de chaîne (sensible à la casse ou non ?)

     

    Private Shared Function CompareByLength( _
       ByVal x As String, ByVal y As String) As Integer
      Dim lc As Int32 = x.Length.CompareTo(y.Length)
      If lc = 0 Then
        Return x.CompareTo(y)
      Else
        Return lc
      EndIf
     End Function
    



    Fred
    • Marqué comme réponse scalpa vendredi 22 juillet 2011 17:50
    vendredi 22 juillet 2011 05:27

Toutes les réponses

  • Bonjour Pascal,

     

    Voici le code testé... ça mérite bien un point ?

     

    Option Explicit On
    Public Class Form1
    
     Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
      Dim a(5) As String ' nombre d'éléments
      Dim i As Integer
      Dim j As Integer
      Dim n As Byte = 2
      Dim v(3) As String
      Dim maxi As Integer = 5
      Me.Hide()
      a(1) = "chat"
      a(2) = "lapinou"
      a(3) = "belette"
      a(4) = "giraffe"
      a(5) = "chien"
      v(1) = "NOMS" & vbLf & a(1) & vbLf & a(2) & vbLf & a(3) & vbLf & a(4) & vbLf & a(5) & vbLf & vbLf
      For i = 1 To maxi ' taille
       For j = 1 To maxi
        If i <> j And Len(a(i)) > Len(a(j)) Then
         a(0) = a(i)
         a(i) = a(j)
         a(j) = a(0)
         Exit For
        End If
       Next j
      Next i
      v(n) = "TAILLE" & vbLf
      For i = 1 To maxi
       If i <> 5 Then v(n) = v(n) & a(i) & vbLf
       If i = 5 Then v(n) = v(n) & a(i) & vbCrLf & vbLf
      Next i
      For j = 1 To maxi
       For i = 1 To maxi - 1 ' taille
        If a(i) > a(i + 1) Then
         a(0) = a(i)
         a(i) = a(i + 1)
         a(i + 1) = a(0)
        End If
       Next i
      Next j
      v(3) = "CLASSE" & vbLf
      n = 3
      For i = 1 To maxi
       If i <> 5 Then v(n) = v(n) & a(i) & vbLf
       If i = 5 Then v(n) = v(n) & a(i) & vbCrLf & vbLf
      Next i
      MsgBox(v(1) & v(2) & v(3))
      End
     End Sub
    End Class
    
    



    Joseph Attila PUSZTAY
    EhJoe       Logiciels       Romans       Ecrire
    • Proposé comme réponse EhJoe jeudi 21 juillet 2011 19:07
    jeudi 21 juillet 2011 15:16
  • Bonjour et merci pour ta réponse Joseph qui mérite sans aucun doute au moins un point!

    Je pense qu'il doit y avoir une solution qui utilise iComparer de la méthode sort en surchargeant comme pour le tri par taille des mots

    Array.Sort(Words, AddressOf CompareByLength,...)
    
    

    comme expliqué ici http://www.codepedia.com/1/VBNET_ArraySort mais je tourne en rond pour l'adaptation...


    Cordialement
    Pascal
    http://www.scalpa.info
    jeudi 21 juillet 2011 18:34
  • Bonsoir Pascal,

     

    Oh moi tu sais, du moment qu'avec le code ça fonctionne, j'adore coder, alors je ne recherche pas mieux, mais pour le second tri, du as tout simplement la listeBox sur sorted=true...

     

    A l'adresse que tu donnes, il fait comme moi sensiblement en utilisant un rangement en tableau de variable avec SPLIT.

     



    Joseph Attila PUSZTAY
    EhJoe       Logiciels       Romans       Ecrire

    • Modifié EhJoe jeudi 21 juillet 2011 19:07 précision
    jeudi 21 juillet 2011 19:04
  • Bonjour,

    Ceci devrait faire l'affaire, mais il faudra peut-être affiner la comparaison de chaîne (sensible à la casse ou non ?)

     

    Private Shared Function CompareByLength( _
       ByVal x As String, ByVal y As String) As Integer
      Dim lc As Int32 = x.Length.CompareTo(y.Length)
      If lc = 0 Then
        Return x.CompareTo(y)
      Else
        Return lc
      EndIf
     End Function
    



    Fred
    • Marqué comme réponse scalpa vendredi 22 juillet 2011 17:50
    vendredi 22 juillet 2011 05:27
  • Bonsoir Fred

    Merci de ta réponse depuis avant hier je bidouille ma fonction pour essayer de comprendre comment ça marche avec l'aide de l'exemple ici : http://www.codepedia.com/1/VBNET_ArraySort  où il y est dit : "Look back at the compare method. You can make it even better. Let's say that x.id = y.id, why not sort it alphabetically now? It isn't hard to implement. All you need to do is say that if x.id - y.id = 0 then if x.name > y.name then return positive number, if it is smaller then return negative and if it is equal then return the one with a bigger salary. There, we just sorted them by all three. First by Id then by name then by salary. Note: The truth be told, Id's should be unique.... but the idea is there."

    Ce qui m'avait conduit à ça.... un peu beurk!!

    Class EmployeeComparer
        Implements IComparer 'Implement the IComparer Interface 
        Overloads Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements IComparer.Compare
          'Return CType(x, Employee).Id - CType(y, Employee).Id
          If x.Id - y.Id = 0 Then
            If x.Name > y.Name Then
              Return 1
            Else
              Return x.Salary - y.Salary
            End If
          End If
          'If x.id is bigger than y.id then x.id-y.id will be positive. 
          'And if y.id is bigger, then x.id-y.id will be negative
          'And finally if they are equal then x.id-y.id will equal zero.
        End Function
      End Class
    

    Je viens de tester ton code et c'est exactement super ! mais une partie de la logique m'échappe :

    1 on compare la taille des mots

    2 si ils sont égaux en taille alors on compare l'ordre alphabétique des mots

    sinon on retourne le résultat >0 ou <0 ?

    Cela a un côté stupéfiant de faire autant de comparaisons en aussi peu de lignes de code.... magique et déroutant !

    Merci de votre aide.

     

     


    Cordialement
    Pascal
    http://www.scalpa.info
    vendredi 22 juillet 2011 17:50
  • Humm, moi je me tournerais vers Linq pour ce genre de problème:
      Sub Main()
        Dim animaux As String() = New String() {
          "chat",
          "lapinou",
          "belette",
          "giraffe",
          "chien"
        }
    
        Dim sort = animaux.OrderBy(Function(g As String) g.Length).ThenBy(Function(g As String) g)
        For Each animal In sort
          Console.WriteLine(animal)
        Next
        Console.ReadLine()
      End Sub
    

    J'ai un peu de misère avec les Lambda en VB (Je suis C#... :) ) mais cela fonctionne bien et es compact.

    Microsoft MVP C# || gabrielmongeon.com || LinkedIn
    vendredi 22 juillet 2011 18:44
    Modérateur
  • Bonjour Pascal,
     
    Par convention, toute classe qui implémente l'interface IComparer doit
    le faire en respectant le contrat suivant :
    - Disposer d'une méthode avec deux arguements (obj1, obj2 les objets à
    comparer) qui retourne un entier.
    - Si les deux objets sont considérés comme égaux, la valeur retournée
    doit être 0
    - Si le premier est "inférieur" au second, la valeur retournée doit être
    négative.
    - Sinon, la valeur retournée doit être positive.
     
    Vois par exemple String.Compare
     
    L' algorithme de tri utilisé (par exemple le QuickSort dans la classe
    ArrayList de base) n'ont besoin que de ce résultat pour pouvoir fonctionner.
    D'autre part, la liste est triée "sur place", sans nécessité
    d'instancier une autre liste ou un autre objet.
     > Je viens de tester ton code et c'est exactement super ! mais une
    > partie de la logique m'échappe :
    >
    > 1 on compare la taille des mots
    >
    > 2 si ils sont égaux en taille alors on compare l'ordre alphabétique
    > des mots
    >
    > sinon on retourne le résultat >0 ou <0 ?
    >
    > Cela a un côté stupéfiant de faire autant de comparaisons en aussi peu
    > de lignes de code.... magique et déroutant !
    >
     
    Oui, c'est exactement cela.
    Hormis le zéro, il n'y a pas de contrainte particulière sur la valeur
    retournée. Cela peut être -1, 0, ou 1 comme -123, 0 ou 4221350 !
     
    On aurait pu l'écrire (c'est d'ailleurs peut-être un peu plus rapide sur
    des volumes importants)
    Dim l1 as Int32 = x.Length
    Dim l2 as Int32 = y.Length
    If x = y Then 'Longueur égale, on renvoie le résultat de la comparaison
    alphabétique
        Return String.Compare(x, y)
    ElseIf x < y Then
        Return -1
    Else
        Return 1
    End If
     
    Autre exemple ici :
     
     

    Fred
    samedi 23 juillet 2011 06:08
  • Bonjour

    Merci pour ces remarques instructives Gabriel, je ne connais rien rien à Linq.... et vais donc me pencher un peu sur la question!

    Merci Fred pour les explications qui éclaircissent le code.

    bonne journée


    Cordialement
    Pascal
    http://www.scalpa.info
    samedi 23 juillet 2011 07:41