天使と悪魔選手権

AとBとCにそれぞれ数値を与えておいて、その数値の大きい順にABCを並べ替えるようにしたいのです。一応、下のようにアルファベットと数値の間にはカンマを入れて分けています。

A, 5-------→B, 9
B, 9-------→C, 7
C, 7-------→A, 5

このように並べ替えたいのですが、うまくいきません。ArrayListを使用しCollectionsクラスのsortメソッドを使ってやれば先頭の文字によるソートはできるのですが、カンマ後の数値での並べ替えの方法がよくわかりません。
いい法方がありましたらおしえてください。

A 回答 (4件)

Harry_さんの回答に賛成ですが、


文字列を格納したArrayListの状態からソートしたいのであれば、
次のようにするといいです。

Collections.sortで、Comparatorを指定しない場合は、
中に入っているオブジェクトのcompareToメソッドを使って、
ソートされます。今回はStringオブジェクトが格納されているので、
StringオブジェクトのcompareToメソッドで比較したソート結果
(文字列を辞書的に並べた結果)でソートされます。
これが、hohumanさんが書いたソースで行っていることです。

今回のように自分独自の比較方法を使用したい場合は、
サンプルのように、自分独自のcompareToメソッドを実装した、
Comparatorを作成して、それをsortするときに使えばいいです。

import java.util.*;
public class Sortable{
  private static ArrayList names; // 名前を格納するArrayList
  
  public static void main(String[] args){
    names = new ArrayList(); // ArrayListオブジェクトの生成
    
    //ファイルから読み込み
    readN();

    //自分で作ったComparableを使って、ソート
    Collections.sort(names, new MyComparator());
    
    for (int i = 0; i < names.size(); i++){
      System.out.println(names.get(i));
    }

  }
  
  //名前をファイルから読み込んでArrayListに格納(しているふり)
  private static void readN(){
    names.add("C, 9");
    names.add("B, 2");
    names.add("A, 7");
  }

  //カンマ後の数値でソートするComparator
  private static class MyComparator implements Comparator{
    public int compare(Object obj1, Object obj2) {
      //文字列データから、ソート対象となる数値を取得
      int num1;
      int num2;
      
      String str1 = obj1.toString();
      String str2 = obj2.toString();
      
      num1 = Integer.parseInt(str1.substring(str1.indexOf(',') + 1).trim());
      num2 = Integer.parseInt(str2.substring(str2.indexOf(',') + 1).trim());
      
      return num2 - num1;
    }
  }
}

ただし、比較するときに、毎回文字列を解析して、
数値の部分を取り出しているので効率は悪いです。
あと、文字列データの仕様が分からないので、
上記ソースは、カンマの後に数値とスペース以外の文字列があると、
数値部分の取り出しに失敗します。
その辺は、実際のデータに合わせて適切な数値部分のとり方を
実装してください。
    • good
    • 0
この回答へのお礼

これを参考にさせてもらいテキストファイルから読み込んだデータのソートもうまくできました。
私もこれからもっといろいろ勉強していきたいと思いますので、また分からない所がありましたら教えてください。
Harryさん、sasadoraさん お二人とも本当にどうもありがとうございました。

お礼日時:2003/01/14 22:41

実行例です。

クラス名やインポート文は補ってください。
コンパイルはしてません。間違ってたらごめんなさい。


public static void main(String[ ] args) {

 Data a = new Data('A', 5) ;
 Data b = new Data('B', 9) ;
 Data c = new Data('C', 7) ;
 List list = Arrays.asList ( new Data[ ]{a, b, c} ) ;
 Collections.sort( list ) ;

 for ( int i = 0 ; i < list.size() ; i++ ) {
  System.out.println( list.get(i) ) ;
 }

}

この回答への補足

うーん、こういうやり方もあるのですね。たいへん勉強になります。
どうもありがとうございます。
しかし今の私の場合、そのように自分でソートするものを入れるのではなく、
テキストファイルなどからその内容を一行一行読み込んでいってソートするように
させています。とりあえず、普通にソートできる状態のものを載せておきます。

(Data2.java)
import java.io.*; //入出力
import java.util.*;

class Data2 {
private static ArrayList names; // 名前を格納するArrayList

public static void main(String[] args) {
names = new ArrayList(); // ArrayListオブジェクトの生成
readN(args[0]);
sort();
print();
}

// 名前を ファイルから 読み込んでArrayListに格納
private static void readN(String fileName) {
try {
FileReader aFileReader = new FileReader(fileName);
BufferedReader aInputFile = new BufferedReader(aFileReader);

// ファイルの終わりに到達するまで名前を読み込む
String aLine;
while ((aLine = aInputFile.readLine()) != null) {
names.add(aLine);
//print(); // 名前が追加されていることを確認のための出力
}

aInputFile.close();
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
}

// 名前の並び替え
private static void sort() {
Collections.sort(names);
}

// 出力
private static void print() {
for (int i = 0; i < names.size(); ++i) {
System.out.println((String)names.get(i));
}
}
}

で、適当なファイル(ABC.txt)を作ってjava Data2 ABC.txtと入力すると
1番前のアルファベット順にソートされます。

(ABC.txt)
C, 9
B, 2
A, 7
 ↓
A, 7
B, 2
C, 9

この状態でカンマの後の数字でのソートをやろうとしています。
もしわかるようでしたら教えてくださいませんか?よろしくお願いします。

補足日時:2003/01/14 01:03
    • good
    • 0

No.1 です。

ちょっと補足です。

数字を大きい方から順に並べるのであれば、
下の回答の compareTo メソッドの return 1 と return -1 は
逆にしないといけません。

この回答への補足

回答どうもありがとうございます。
さっそく試してみたのですがコンパイル時にこのようなエラーが発生しました

C:\JAVA\Sort4.java:32: \12288 は不正な文字です。
 this.alphabet = alphabet;
^
C:\JAVA\Sort4.java:33: \12288 は不正な文字です。
 this.number = number;
^
C:\JAVA\Sort4.java:42: \12288 は不正な文字です。
  return alphabet + ", " + number;
^
この場合、何が原因なのか分かりますか?

補足日時:2003/01/12 18:42
    • good
    • 0
この回答へのお礼

すみません、補足のは取り消しです。
ただのスペースの問題でした。

お礼日時:2003/01/12 19:16

1レコードのデータをひとつのクラスで表現すべきです。



public class Data {
 private char alphabet;
 private int number;
 public Data(char alphabet, int number) {
  this.alphabet = alphabet;
  this.number = number;
 }
 public char getAlphabet() { return alphabet; }
 public int getNumber() { return number; }
}

そして、このクラスに Comparable インターフェースをインプリメントさせ、
compareTo メソッドを実装します。

public class Data implements Comparable {

// 上記と同じ

// これを追加
 public int compareTo(Object obj) {
  Data other = (Data)obj;
  if (this.number > other.number) {
   return 1;
  }
  else if (this.number < other.number) {
   return -1;
  }
  else {
   return 0;
  }

}


そのうえで、このクラスのオブジェクトを格納した List を Collections.sort()
でソートすると、数字の大きさでソートできます。

ついでに toString() も実装しておくとよいですね。

public String toString() {
 return alphabet + ", " + number;
}

この回答への補足

>このクラスのオブジェクトを格納した List ・・・
の部分をどのようにすればいいのか、いまいちよくわかりません。

もしよろしければ実行例をお願いできないでしょうか?
まだまだ勉強不足なものですみません・・・・・。

補足日時:2003/01/12 21:52
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報