どのように私は私が望むようこのArrayListのを並べ替えることができますか?

StackOverflow https://stackoverflow.com/questions/890254

  •  23-08-2019
  •  | 
  •  

質問

ここでのArrayListの簡単なソートプログラムがあります:

ArrayList<String> list = new ArrayList<String>();

list.add("1_Update");
list.add("11_Add");
list.add("12_Delete");
list.add("2_Create");

Collections.sort(list);
for (String str : list) {
  System.out.println(str.toString());
}

私は、このプログラムの出力を期待していました

1_Update
2_Create
11_Add
12_Delete

しかし、私はこのプログラムを実行すると、私はのような出力を取得しています:

11_Add
12_Delete
1_Update
2_Create

なぜこれがあると予想される出力に示すように、どのように私は、ArrayListには、ソートするのですか?

役に立ちましたか?

解決

カスタムコンパレータを書くことができます:

Collections.sort(list, new Comparator<String>() {
    public int compare(String a, String b) {
        return Integer.signum(fixString(a) - fixString(b));
    }
    private int fixString(String in) {
        return Integer.parseInt(in.substring(0, in.indexOf('_')));
    }
});

他のヒント

あなたは文字列としてこのタイプのデータを並べ替える場合は、

、それは数字を含む文字そのものを、比較しています。 「1」で始まる文字列のすべては、例えば、一緒になってしまいます。だから、順序はこれに似て終わる...

1 10 100 2 20 200

どの時点でソートを使用すると、文字列の先頭に可変長の数字として、文字列のサブセットに意味を割り当てること「を実現」ん。文字列として数値をソートする場合、最大数をカバーするのに必要なだけゼロで左側にパディングを助けることができますが、あなたはあなたの例のように、データをコントロールしていないとき、それは本当に問題を解決していません。その場合は、ソートは以下のようになり...。

001 002 010 020 100 200

これは、テキスト(アルファベット順)など、ない数字としてソートされます。 nsayerによって答えで提案されているようにこの問題を回避するには、カスタムコンパレータを実装することができます。

これは、辞書的な比較を行っています。これは、それらを並べ替え、各文字列の最初の文字を比較します。その後、同じ第1 charaterとのそれらの2番目の文字列を比較します。それは数に「_」文字を比較した場合、それは文字比較ではなく、数値の比較を行っている覚えているだけで8> 7> 9のような任意の単一の数の文字よりも値が大きいます。

スクリプト名の名前を変更するよりも良いかもしれ独自のカスタム並べ替えのルーティングを実装する方法があります。

スクリプト名の名前を変更するオプションがある場合、これは他のスクリプトツールが使用できるようにすることができます。一つの形式はかもしれ

01_create_table.sql
02_create_index.sql
11_assign_privileges.sql

2つの文字にあなたの最初の2桁を維持することによって、辞書式の比較が動作します。

Collections.sort()メソッドのドキュメントは述べています:

  

に指定されたリストをソートします   によると、昇順   その要素の自然順序付けます。

あなたはアルファベット順で一覧を取得しようとしている文字列のことを意味します。プログラムが正常に機能しているように文字列の1_create_table.sqlと12_07_insert_static_data.sqlが1_create_table.sqlなどの前に来る前に、文字列11_assign_privileges.sqlが来ます。

の文字列がアルファベットの順序でソートされ、下線文字は、番号の文字の後にあるので。あなたは、所望の結果を達成するために、「自然の秩序」を実施コンパレータを提供する必要があります。

の文字列は、アルゴリズムをコンペア時に各文字 を。 12の前に並べ替えます。それはそれは1または2が続いていることは重要ではありません。

だから、1002の前に並べ替えます。この動作を望まない場合は、このケースを扱う比較アルゴリズムを必要とします。

他の人が述べたように、

、要素はデフォルトでアルファベット順にソートされます。溶液は、コンクリートはjava.util.Comparatorクラスを定義し、ソート方法の2番目の引数として渡しています。あなたのコンパレータは、文字列から先頭の整数を解析し、それらを比較する必要があります。

Collection.sortを(持っているために)ソート任意に使用することができます。

Collections.sort(List list, Comparator c)  

そして、単に最初の数に基づいて、その後、残りのかしかし、あなたはそれをソートしたい文字列と種類を分割コンパレータを実装します。

誰もがすでに説明は、あなたの文字列が文字列としてソートされ、その数はすでに自然順文字列比較に注意を向けるしていることであることを指摘しています。私はちょうどそれがコンパレータ自分自身、そしてテスト駆動開発を実践する絶好の機会を書くために偉大な運動だと追加します。私は、コードキャンプでTDDを証明するためにそれを使用しました。スライド&コードはここをです。

あなたは、特定のプロパティでソートその後、IComparableインターフェイスを追加することができます。あなたが例えば店舗の項目のコレクションを持っている場合は、多分あなたは名前で注文したい場合は価格で、カテゴリなどによってそれらをソートしたいここに例を示します。

ArrayListのはアイテムのnameプロパティでソートされているかに注意してください。あなたはIComparableをを追加しない場合は、ソート方法を使用する場合、それはエラーがスローされます。

ここに画像の説明を入力します

static void Main(string[] args)
    {
        ArrayList items = new ArrayList();
        items.Add(new Item("book", 12.32));
        items.Add(new Item("cd", 16.32));
        items.Add(new Item("bed", 124.2));
        items.Add(new Item("TV", 12.32));

        items.Sort();

        foreach (Item temp in items)
            Console.WriteLine("Name:{0} Price:{1}", temp.name, temp.price);
        Console.Read();            
    }


    class Item: IComparable
    {
        public string name;
        public double price;

        public Item(string _name, double _price)
        {
            this.name = _name;
            this.price = _price;
        }

        public int CompareTo(object obj)
        {   
            //note that I use the name property I may use a different one
            int temp = this.name.CompareTo(((Item)obj).name);
            return temp;
        }
    }
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top