web-dev-qa-db-fra.com

Pourquoi ma boucle de tri semble-t-elle ajouter un élément là où elle ne devrait pas?

J'essaie de trier un tableau de chaînes en utilisant compareTo(). Ceci est mon code:

static String Array[] = {" Hello ", " This ", "is ", "Sorting ", "Example"};
String temp;

public static void main(String[] args)
{

   for (int j=0; j<Array.length;j++)
   {
       for (int i=j+1 ; i<Array.length; i++)
       {
           if (Array[i].compareTo(Array[j])<0)
           {
               String temp = Array[j];
               Array[j] = Array[i];
               Array[i] = temp;
           }
       }
       System.out.print(Array[j]);
   }
}

Maintenant, le résultat est:

Hello  This Example Sorting is

J'obtiens des résultats, mais pas ceux que je veux obtenir, qui sont:

Hello This Example Is Sorting

Comment puis-je ajuster mon code pour trier le tableau de chaînes correctement?

70
Sikander

Votre sortie est correcte. Indiquez les caractères blancs de "Bonjour" et "Ceci" au début.

Un autre problème concerne votre méthodologie. Utilisez la méthode Arrays.sort():

String[] strings = { " Hello ", " This ", "Is ", "Sorting ", "Example" };
Arrays.sort(strings);

Sortie:

 Hello
 This
Example
Is
Sorting

Ici, le troisième élément du tableau "is" devrait être "Is", sinon il entrera en dernier après le tri. Parce que la méthode de tri utilise en interne la valeur ASCII pour trier les éléments.

146
Juvanis

Mis à part les solutions alternatives qui ont été publiées ici (qui sont correctes), personne n’a réellement répondu à votre question en indiquant ce qui n'allait pas avec votre code.

Il semble que vous essayiez de mettre en œuvre un algorithme tri de sélection . Je n'entrerai pas dans les détails du fonctionnement du tri ici, mais j'ai inclus quelques liens pour votre référence =)

Votre code était syntaxiquement correct, mais logiquement faux. Vous triiez partiellement vos chaînes en comparant chaque chaîne avec les chaînes suivantes . Voici une version corrigée (j'ai conservé autant de votre code original pour illustrer ce qui était "faux" avec elle):

static  String Array[]={" Hello " , " This " , "is ", "Sorting ", "Example"};
String  temp;

//Keeps track of the smallest string's index
int  shortestStringIndex; 

public static void main(String[] args)  
{              

 //I reduced the upper bound from Array.length to (Array.length - 1)
 for(int j=0; j < Array.length - 1;j++)
 {
     shortestStringIndex = j;

     for (int i=j+1 ; i<Array.length; i++)
     {
         //We keep track of the index to the smallest string
         if(Array[i].trim().compareTo(Array[shortestStringIndex].trim())<0)
         {
             shortestStringIndex = i;  
         }
     }
     //We only swap with the smallest string
     if(shortestStringIndex != j)
     {
         String temp = Array[j];
         Array[j] = Array[shortestStringIndex]; 
         Array[shortestStringIndex] = temp;
     }
 }
}

Lectures supplémentaires

Le problème avec cette approche est que sa complexité asymptotique est O (n ^ 2) . En termes simplifiés, il devient très lent lorsque la taille du tableau augmente (approche de l'infini). Vous voudrez peut-être lire à propos de meilleures façons de trier les données , tel que quicksort .

15
Prince Mabandla

Je sais que c'est une réponse tardive, mais peut-être que cela peut aider quelqu'un.

La suppression des espaces peut être effectuée à l'aide de la fonction trim (). Après cela, si vous souhaitez trier le tableau de manière sensible à la casse, vous pouvez simplement utiliser:

Arrays.sort(yourArray);

et de manière insensible à la casse:

Arrays.sort(yourArray,String.CASE_INSENSITIVE_ORDER);

J'espère que cela t'aides!

9
RishikeshD

Au lieu de cette ligne

if(Array[i].compareTo(Array[j])<0)

utiliser cette ligne

if(Array[i].trim().compareTo(Array[j].trim())<0)

et vous êtes prêt à partir. La raison pour laquelle votre code actuel ne fonctionne pas est déjà expliquée par d'autres utilisateurs. Ce remplacement ci-dessus est une solution parmi plusieurs que vous pouvez appliquer.

9
narayanf1

À partir de Java 8 , vous pouvez également utiliser parallelSort , ce qui est utile si vous avez des tableaux contenant de nombreux éléments.

Exemple:

public static void main(String[] args) {
    String[] strings = { "x", "a", "c", "b", "y" };
    Arrays.parallelSort(strings);
    System.out.println(Arrays.toString(strings));   // [a, b, c, x, y]
}

Si vous voulez ignorer la casse , vous pouvez utiliser:

public static void main(String[] args) {
    String[] strings = { "x", "a", "c", "B", "y" };
    Arrays.parallelSort(strings, new Comparator<String>() {
        @Override
        public int compare(String o1, String o2) {              
            return o1.compareToIgnoreCase(o2);
        }
    });
    System.out.println(Arrays.toString(strings));   // [a, B, c, x, y]
}

sinon B sera avant a.

Si vous voulez ignorer les espaces de fin lors de la comparaison, vous pouvez utiliser trim():

public static void main(String[] args) {
    String[] strings = { "x", "  a", "c ", " b", "y" };
    Arrays.parallelSort(strings, new Comparator<String>() {
        @Override
        public int compare(String o1, String o2) {              
            return o1.trim().compareTo(o2.trim());
        }
    });
    System.out.println(Arrays.toString(strings)); // [  a,  b, c , x, y]
}

Voir :

5
ROMANIA_engineer

Si tu utilises:

if (Array[i].compareToIgnoreCase(Array[j]) < 0)

tu auras:

Example  Hello  is  Sorting  This

ce que je pense est la sortie que vous cherchiez.

4
Eduard Ghinea

" Hello " , " This " , "is ", "Sorting ", "Example"

Tout d'abord, vous avez fourni des espaces dans " Hello " et " This ", les espaces ont une valeur inférieure à celle des caractères alphabétiques dans Unicode, ils sont donc imprimés en premier. (Le reste des caractères ont été triés par ordre alphabétique).

Les lettres majuscules ont maintenant une valeur inférieure à celle des minuscules en Unicode. Ainsi, "Exemple" et "Tri" sont imprimés, puis enfin "is " qui a la valeur la plus élevée.

4
Udit Seth

Pour commencer, votre problème est que vous utilisez la méthode `compareTo () qui est sensible à la casse. Cela signifie que les lettres majuscules sont séparées des minuscules. La raison en est qu’elle est traduite en Unicode où les lettres majuscules sont présentées avec des nombres inférieurs au nombre présenté de minuscules. Ainsi, vous devriez utiliser `compareToIgnoreCase ()` en tant que beaucoup également mentionné dans les messages précédents.

Ceci est mon exemple complet d’approche de la façon dont vous pouvez le faire efficacement.

Après avoir créé un objet de la Comparateur vous pouvez le transmettre dans cette version de `sort ()` définie dans Tableaux Java.util.

static<T>void sort(T[]array,Comparator<?super T>comp)

regarde de près super. Cela garantit que le tableau transmis est compatible avec le type de comparateur.

La partie magique de cette façon est que vous pouvez facilement trier le tableau de chaînes Ordre inverse vous pouvez facilement le faire en:

return strB.compareToIgnoreCase(strA);
import Java.util.Comparator;

    public class IgnoreCaseComp implements Comparator<String> {

        @Override
        public int compare(String strA, String strB) {
            return strA.compareToIgnoreCase(strB);
        }

    }
  import Java.util.Arrays;

    public class IgnoreCaseSort {

        public static void main(String[] args) {
            String strs[] = {" Hello ", " This ", "is ", "Sorting ", "Example"};
            System.out.print("Initial order: ");

            for (String s : strs) {
                System.out.print(s + " ");
            }

            System.out.println("\n");

            IgnoreCaseComp icc = new IgnoreCaseComp();

            Arrays.sort(strs, icc);

            System.out.print("Case-insesitive sorted order:  ");
            for (String s : strs) {
                System.out.print(s + " ");
            }

            System.out.println("\n");

            Arrays.sort(strs);

            System.out.print("Default, case-sensitive sorted order: ");
            for (String s : strs) {
                System.out.print(s + " ");
            }

            System.out.println("\n");
        }

    }
 run:
    Initial order:  Hello   This  is  Sorting  Example 

    Case-insesitive sorted order:   Hello   This  Example is  Sorting  

    Default, case-sensitive sorted order:  Hello   This  Example Sorting  is  

    BUILD SUCCESSFUL (total time: 0 seconds)

Choix alternatif

La méthode compareToIgnoreCase(), bien que cela fonctionne bien avec de nombreuses occasions (comme avec chaîne de comparaison en anglais), ne fonctionnera pas bien avec tous les langues et lieux. Cela en fait automatiquement un choix impropre à l’utilisation. Pour vous assurer qu'il sera pris en charge partout, vous devez utiliser compare() de Java.text.Collator.

Vous pouvez trouver un assembleur pour votre emplacement en appelant la méthode getInstance(). Après cela, vous devez définir la propriété de force de ce collateur. Cela peut être fait avec la méthode setStrength() avec le paramètre Collator.PRIMARY. Avec cette variante, le IgnocaseComp peut être écrit comme ci-dessous. Cette version de code générera la même sortie indépendamment de l'emplacement

import Java.text.Collator;
import Java.util.Comparator;

//this comparator uses one Collator to determine 
//the right sort usage with no sensitive type 
//of the 2 given strings
public class IgnoreCaseComp implements Comparator<String> {

    Collator col;

    IgnoreCaseComp() {
        //default locale
        col = Collator.getInstance();

        //this will consider only PRIMARY difference ("a" vs "b")
        col.setStrength(Collator.PRIMARY);
    }

    @Override
    public int compare(String strA, String strB) {
        return col.compare(strA, strB);
    }

}
3