【问题标题】:How do I sort an array of strings based on different parts of each string?如何根据每个字符串的不同部分对字符串数组进行排序?
【发布时间】:2012-09-18 18:23:25
【问题描述】:

我必须按获得的金牌数量以降序对国家/地区进行排序。如果有几个国家并列,我需要按银牌数量对并列的国家进行排序,然后是铜牌,如果还有平局,我需要按字母升序对它们进行排序。我已经编写了一个比它可能需要的复杂得多的程序,但它仍然返回字符串的无序列表。输入是按年份给出的,第一个国家是金牌得主,第二个是银牌,第三个是铜牌。例如:

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

}

这会返回:

澳大利亚 0 0 1 中国 0 1 0 英国 0 0 1 意大利 1 0 0 日本 0 1 0 韩国 3 1 0 热塑性弹性体 0 1 1 英镑 0 0 1

但是,我在尝试订购上面的输出时遇到了一些严重的问题。我怎样才能像现在这样按奖牌的值而不是按字母顺序排列它们?

【问题讨论】:

  • 不要使用数组!使用集合,列表。相信我...

标签: java sorting map


【解决方案1】:

Java 是一种面向对象的语言,使用一些对象来做到这一点。 创建某种类来表示一个国家,其中包含用于存储金、银和铜牌以及国家名称的变量。

在该类(称为Country)中实现Comparable interface,您可以在其中实现您定义的排序规则。

在您正在运行的程序中,您创建一个Country 对象列表并使用Collections.sort() 进行排序

【讨论】:

    【解决方案2】:

    我认为解决这个问题的更好方法是创建一个这样的类:

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

    正确定义 compareTo(它是 Comparable&lt;T&gt; interface 的一部分)方法后,您应该可以使用 Collections.sortArrays.sort 对列表进行排序,如果您坚持使用数组而不是列表。

    OlympicCountry 类的 toString 方法负责正确格式化数据以供显示(或您打算用它做什么)。

    实现这样的对象来存储和操作原始数据通常是一种更好的设计,而不是将其全部放入字符串或整数或其他东西中,然后尝试对其进行操作。这就是我们可以声明自己的类的原因。

    【讨论】:

    • 我以前从未见过这种情况(抱歉,有点像 Java 新手)。如何编写 compareTo 方法?
    • 这就是上面的代码示例向您展示的内容。我省略了构造函数和compareTo 方法的两行,但您应该可以自己填写这些空白。
    • 啊,好的,谢谢。这需要我一点时间,但这绝对是一个更好的方法。
    • 正如 elber 在下面的回答中指出的那样,我的 compareTo 方法可能会给你一个不同于你想要的顺序(最少到大多数奖牌)。如果您想换一种方式,只需将compareTo 方法中的&gt; 符号更改为&lt; 符号即可。
    • 太棒了,是的,当我得到一些奇怪的答案并完成我的代码时,我想通了。感谢您的帮助!
    【解决方案3】:

    这是将 Comparable 添加到 OlympicCountry 答案中的 treeSet

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

    【讨论】:

    • 首先,你几乎只是提升了我的代码(抄袭并不酷——你至少应该说你在扩展我的答案)。其次,它以多种方式被完全破坏(例如,! 运算符未声明为 int 类型)。
    • 你是对的,在我看来,我在代码中实现并粘贴在这里,看到你已经这样做了(和我一样,然后我删除了我的部分并保持主要方法)。按照 !我弄错了:(对不起。应该是 - 签名。
    • 我没有想到顺序需要倒退。声明像您这样的比较器确实有效,或者您可以更改 compareTo 定义以按正确顺序排序。感谢您指出这一点。
    猜你喜欢
    • 1970-01-01
    • 2015-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-17
    • 1970-01-01
    • 2020-02-20
    • 1970-01-01
    相关资源
    最近更新 更多