web-dev-qa-db-ja.com

ソートループで要素を追加すべきでない場所に追加するように見えるのはなぜですか?

compareTo()を使用して文字列の配列をソートしようとしています。これは私のコードです:

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]);
   }
}

現在の出力は次のとおりです。

Hello  This Example Sorting is

結果を取得していますが、取得したい結果ではありません。

Hello This Example Is Sorting

コードを調整して文字列配列を適切にソートするにはどうすればよいですか?

70
Sikander

出力は正しいです。先頭にある「Hello」と「This」の白い文字を示します。

別の問題は、方法論にあります。 Arrays.sort()メソッドを使用します。

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

出力:

 Hello
 This
Example
Is
Sorting

ここで、配列「is」の3番目の要素は「Is」である必要があります。そうでない場合、ソート後に最後に配置されます。並べ替え方法は内部でASCII値を使用して要素を並べ替えるためです。

146
Juvanis

ここに投稿された代替ソリューション(正しい)を除いて、コードの何が問題だったのかを解決してあなたの質問に実際に答えた人はいません。

選択ソート アルゴリズムを実装しようとしているようです。ここではソートの仕組みの詳細には触れませんが、参照用のリンクをいくつか追加しました=)

コードは構文的には正しいが、論理的に間違っていた。各文字列をその後に続く文字列と比較するだけで、文字列を部分的に並べ替えていました。修正版を以下に示します(元のコードの大部分を保持して、それが「間違った」ものであることを示します)。

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;
     }
 }
}

さらに読む

このアプローチの問題は、その 漸近的な複雑さがO(n ^ 2) であることです。簡単に言えば、配列のサイズが大きくなると(無限に近づくと)非常に遅くなります。 quicksort などの データを並べ替えるより良い方法 について読みたいかもしれません。

15
Prince Mabandla

これは返信が遅いことを知っていますが、誰かを助けることができるかもしれません。

空白を削除するには、trim()関数を使用します。その後、大文字と小文字を区別して配列を並べ替える場合は、次を使用できます:

Arrays.sort(yourArray);

大文字と小文字を区別しない方法の場合:

Arrays.sort(yourArray,String.CASE_INSENSITIVE_ORDER);

お役に立てれば!

9
RishikeshD

この行の代わりに

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

この行を使用

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

そしてあなたは行ってもいいです。現在のコードが機能しない理由は、すでに他のユーザーによって説明されています。上記の置き換えは、適用可能ないくつかの回避策の1つです。

9
narayanf1

Java 8から始めて、 parallelSort を使用することもできます。これは、多くの要素を含む配列がある場合に便利です。

例:

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]
}

ケースを無視したい場合は、以下を使用できます:

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]
}

それ以外の場合、Baの前になります。

比較中に末尾のスペースを無視したい場合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]
}

参照

5

使用する場合:

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

あなたが取得します:

Example  Hello  is  Sorting  This

あなたが探していた出力だと思います。

4
Eduard Ghinea

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

まず、" Hello "および" This "でスペースを指定すると、スペースはUnicodeのアルファベット文字よりも低い値を持つため、最初に印刷されます。 (残りの文字はアルファベット順にソートされています)。

大文字はUnicodeの小文字よりも低い値を持つようになったため、「Example」と「Sorting」が出力され、最後に最大値を持つ"is "が印刷されます。

4
Udit Seth

まず、問題は、大文字と小文字を区別するメソッド `compareTo()を使用することです。つまり、大文字は小文字とは別にソートされます。その理由は、ユニコードで変換され、大文字が、表示された小文字の数よりも少ない数字で表示されるためです。したがって、以前の投稿でも触れたように、 `compareToIgnoreCase()`を使用する必要があります。

これは、効果的な方法の私の完全な例のアプローチです

のオブジェクトを作成した後 コンパレータ で定義したこのバージョンの `sort()`で渡すことができます Java.util.Arrays

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

よく見てください スーパー。 これにより、渡される配列がコンパレーターのタイプと競合することが確実になります。

この方法の魔法の部分は、文字列の配列を簡単にソートできることです 逆順 次の方法で簡単にできます。

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)

代替選択肢

メソッドcompareToIgnoreCase()は、多くの場合(英語の文字列を比較するように)うまく機能しますが、すべての言語と場所ではうまく機能しません。これにより、自動的に使用に適さない選択肢になります。すべての場所でサポートされるようにするには、Java.text.Collat​​orcompare()を使用する必要があります。

getInstance()メソッドを呼び出すことにより、現在の場所のコレーターを見つけることができます。その後、このCollat​​orの強度プロパティを設定する必要があります。これは、パラメータとしてCollator.PRIMARYとともにsetStrength()メソッドを使用して実行できます。この代替選択肢では、IgnocaseCompは次のように記述できます。このバージョンのコードは、場所に関係なく同じ出力を生成します

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