简体   繁体   中英

How do I sort an array of strings based on different parts of each string?

I have to sort countries by the number of gold medals won in decreasing order. If several countries are tied, I need to sort the tied countries by the number of silver medals, then bronze metals, then if there's still a tie, I need to sort them by ascending alphabetical order. I have already written a program that is much more complex than it probably needs to be, but it still returns the unordered list of strings. The inputs are given by the years, with the first country being the gold medal winner, the second silver, and the third bronze. eg:

public class MedalTable {
public static void main(String[] args){
    String[] input = {"ITA JPN AUS", "KOR TPE UKR", "KOR KOR GBR", "KOR CHN TPE"};
    generate(input);

}

public static void generate(String[] results) {
    // you fill in this code
    //"ITA JPN AUS", "KOR TPE UKR", "KOR KOR GBR", "KOR CHN TPE"
    String[] countrystrings = setupstuff(results);
    ArrayList<Integer> goldnums = new ArrayList<Integer>();
    ArrayList<Integer> silvnums = new ArrayList<Integer>();
    ArrayList<Integer> broznums = new ArrayList<Integer>();

    for(int o = 0; o < countrystrings.length; o++){
        goldnums.add(Integer.parseInt(Character.toString(countrystrings[o].charAt(4))));
        silvnums.add(Integer.parseInt(Character.toString(countrystrings[o].charAt(6))));
        broznums.add(Integer.parseInt(Character.toString(countrystrings[o].charAt(8))));
    }


}

public static String[] setupstuff(String[] data){
    Map<String, Integer> goldmap = new TreeMap<String, Integer>();
    Map<String, Integer> silvermap = new TreeMap<String, Integer>();
    Map<String, Integer> bronzemap = new TreeMap<String, Integer>();
    ArrayList<String> goldlist = new ArrayList<String>();
    ArrayList<String> silverlist = new ArrayList<String>();
    ArrayList<String> bronzelist = new ArrayList<String>();
    ArrayList<String> countries = new ArrayList<String>();
    for (String i : data){
        goldlist.add(i.substring(0, 3));
        silverlist.add(i.substring(4, 7));
        bronzelist.add(i.substring(8, 11));
    }
    populatemap(goldmap, goldlist);
    populatemap(silvermap, silverlist);
    populatemap(bronzemap, bronzelist);
    countries = getuniquecountries(goldmap, silvermap, bronzemap);
    String[] countrystrings = new String[countries.size()];
    countrystrings = createmedalstring(countries, goldmap, silvermap, bronzemap);
    Arrays.sort(countrystrings);
    for(int v = 0; v < countrystrings.length; v++){
        System.out.println(countrystrings[v]);
    }
    return countrystrings;
}

public static String[] createmedalstring(ArrayList<String> array, Map<String, Integer> gldmap,
        Map<String, Integer> slvmap, Map<String, Integer> brzmap){
    String[] thiscountry = new String[array.size()];
    ArrayList<String> tempstring = new ArrayList<String>();
    for (int j = 0; j < array.size(); j++){
        thiscountry[j] = array.get(j);
    }
    String[] concatstuff = new String[thiscountry.length];
    for (int k = 0; k < thiscountry.length; k++){
        concatstuff[k] = thiscountry[k];
    }
    for (int i = 0; i < thiscountry.length; i++){
        tempstring.add(thiscountry[i]);
        if(gldmap.containsKey(thiscountry[i])){
            tempstring.add(" " + gldmap.get(array.get(i).toString()));
        }
        else{
            tempstring.add(" 0");
        }
        if(slvmap.containsKey(thiscountry[i])){
            tempstring.add(" " + slvmap.get(array.get(i).toString()));
        }
        else{
            tempstring.add(" 0");
        }
        if(brzmap.containsKey(thiscountry[i])){
            tempstring.add(" " + brzmap.get(array.get(i).toString()));
        }
        else{
            tempstring.add(" 0");
        }
        concatstuff[i] = tempstring.get(0) + tempstring.get(1) + tempstring.get(2) + tempstring.get(3);
        tempstring.clear();
    }
    return concatstuff;
}

public static ArrayList<String> getuniquecountries(Map<String, Integer> gldmap, 
        Map<String, Integer> slvmap, Map<String, Integer> brzmap){
    ArrayList<String> countries = new ArrayList<String>();
    for(Entry<String, Integer> i : gldmap.entrySet()){
        if(!countries.contains(i.getKey()))
            countries.add(i.getKey());
    }
    for(Entry<String, Integer> j : slvmap.entrySet()){
        if(!countries.contains(j.getKey()))
            countries.add(j.getKey());
    }
    for(Entry<String, Integer> k : brzmap.entrySet()){
        if(!countries.contains(k.getKey()))
            countries.add(k.getKey());
    }
    return countries;
}

public static void populatemap(Map<String, Integer> map, ArrayList<String> array){
    for (String i : array){
        if(map.containsKey(i)){
            map.put(i, map.get(i) + 1);
        }
        else{
        map.put(i, 1);
        }
    }
    //System.out.println(map);
}

}

This returns:

AUS 0 0 1 CHN 0 1 0 GBR 0 0 1 ITA 1 0 0 JPN 0 1 0 KOR 3 1 0 TPE 0 1 1 UKR 0 0 1

However, I am having some serious issues in trying to order the output above. How can I order them by the values of the medals instead of alphabetically, like they are now?

I think a better way to approach the problem would be to create a class like this:

class OlympicCountry implements Comparable<OlympicCountry> {
  private int goldCount;
  private int silverCount;
  private int bronzeCount;
  private String name;

  // . . .

  public String toString() {
    return String.format("%s %d %d %d", name, goldCount, silverCount, bronzeCount);
  }

  public int compareTo(OlympicCountry other) {
    if (this.goldCount != other.goldCount)
      return this.goldCount > other.goldCount ? 1 : -1;
    if (this.silverCount != other.silverCount)
      return this.silverCount > other.silverCount ? 1 : -1;
    // . . .
    return this.name.compareTo(other.name);
  }
}

After properly defining the compareTo (which is part of the Comparable<T> interface ) method you should be able to sort your list using Collections.sort , or Arrays.sort if you insist on using arrays rather than lists.

The OlympicCountry class's toString method takes care of formatting the data correctly for display (or whatever it is you plan on doing with it).

It's typically a much better design to implement an object like this for storing and manipulating the raw data rather than shoving it all in a String or an integer or something and trying to manipulate it afterwards. That's the reason we can declare our own classes after all.

Here is treeSet with Comparable adding to the OlympicCountry answer

public class OlympicCountry implements Comparable<OlympicCountry> {


    public static void main(String args[]){
        Set<OlympicCountry> set = new TreeSet<OlympicCountry>(new Comparator<OlympicCountry>() {
            @Override
            public int compare(OlympicCountry o1, OlympicCountry o2) {
                return -o1.compareTo(o2);
            }
        });

        OlympicCountry c1 = new OlympicCountry();
        // set values to c1
        set.add(c1);

        OlympicCountry c2 = new OlympicCountry();
        // set values to c2
        set.add(c2);

    }
}

Java is an Object-Oriented Language use some Objects to do this. Create some kind of Class to represent a Country with variables to store gold, silver and bronze medals as well as the name of the country.

In that class (calling it Country ) implement the Comparable interface where you can implement the sorting rules you have defined.

In your running program you create a list of Country objects and sort using Collections.sort()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM