【问题标题】:Printing information from arrays, without using duplicate values从数组打印信息,而不使用重复值
【发布时间】:2014-04-02 10:14:58
【问题描述】:

我正在编写一个程序,它接收奥运奖牌数据,并打印出各种信息。就逻辑和结构而言,这个特定部分被证明有点困难。我正在尝试获取 String arrayint array(它们都是在 main 方法中创建的),将它们传递给新方法,并打印出有关它们的信息。

我的数组如下(请注意String数组是按字母顺序排列的):

        String[] country = {"Afghanistan", "Afghanistan", "Canada", "China", "Italy", "Mexico"};
        int[] totalMedals = {1, 2, 1, 1, 3, 2};

我想打印出来如下:

Afghanistan, 3 medal(s)
Canada, 1 medal(s)
China, 1 medal(s)
Italy, 3 medal(s)
Mexico, 2 medal(s)

我可以很容易地编写以这种格式列出的程序,但是出现不止一次的国家(在这个示例中...阿富汗)被列出的次数与它在数组中出现的次数一样多。正如所写,我的输出是:

Afghanistan, 1 medal(s)
Afghanistan, 2 medal(s)
Canada, 1 medal(s)
China, 1 medal(s)
Italy, 3 medal(s)
Mexico, 2 medal(s)

阿富汗被列出了两次(为了提供一个重要的背景,这是该计划的一小部分。该计划实际上也包含运动员的名字,但以不同的方式处理)。

任何人都可以就打印出我想要的输出的最佳方式向我提供一些帮助吗?

import java.util.*;
import java.io.*;

public class Project {

public static void main(String[] args) {
    String[] country = {"Afghanistan", "Afghanistan", "Canada", "China", "Italy", "Mexico"};
    int[] totalMedals = {1, 2, 1, 1, 3, 2};

    listCountryMedals(country, totalMedals);

}

    //List the grand total of medals for each country...display name only once
public static void listCountryMedals(String[] country, int[] totalMedals) {

    for (int i = 0; i < country.length; i++) {
        System.out.println(country[i] + ", " + totalMedals[i] + " medal(s)");            
    }
}

【问题讨论】:

    标签: java arrays


    【解决方案1】:

    假设您只想使用数组和循环,您可以执行以下操作:

    public static void listCountryMedals(String[] country, int[] totalMedals) {
      boolean[]seen = new boolean[country.length];
      for (int i = 0; i < country.length - 1; i++) {
          int medals = totalMedals[i];
          if (!seen[i]) {
              for(int j = i + 1; j < country.length; j++) {
                 if (country[i].equals(country[j])) {
                     medals += totalMedals[j];
                     seen[j] = true; //I already took this country
                 }
              }
              System.out.println(country[i] + ", " + medals + " medal(s)");
          }
          seen[i] = true;
      }
    }
    

    【讨论】:

    • 与所有基于地图的答案(复杂度 O(n))相反,这个答案的复杂度是 O(n²)。这对于更大的列表可能很重要。
    • 哦,我不喜欢这个。为什么不直接使用某种Set 来表示所见国家,而不是boolean[]?那么你就不需要那个内部循环和所有那些额外的比较了。
    • 我完全同意@FlorentBayle 提到的这种解决方案效率低下,当然 set 或 HashMap 是更优雅的解决方案。但是,我相信提出这个问题的人还不熟悉对象和类,但他只知道方法和 main() 作为程序的起点。他也很聪明,这就是为什么我相信他正在尝试更多的东西。这来自我的教学经验,我经常会发现这样的问题。所以我选择了一个对提出问题的人来说有意义的答案。
    【解决方案2】:

    试试这个,

    public static void listCountryMedals(String[] country, int[] totalMedals)
        {
            Map<String, Integer> countryMap = new HashMap<String, Integer>();
    
            for (int i = 0; i < country.length; i++)
            {
                Integer medals = countryMap.get(country[i]);
                Integer sum = (medals == null) ? totalMedals[i] : (totalMedals[i] + medals);
                countryMap.put(country[i], sum);
            }
    
            for (Map.Entry<String, Integer> countryMedals : countryMap.entrySet())
            {
                System.out.println(countryMedals.getKey() + ", " + countryMedals.getValue() + " medal(s)");
            }
        }
    

    【讨论】:

    • 您可以通过在 if 语句之前执行 countryMap.get(country[i]); 来稍微简化这一点,将其分配给 Integer 并将 if 条件更改为 if (medals != null) 或将其替换为三元运算符。
    • 不,不是那样的!你所做的根本不是我的意思;我认为现在稍微复杂一些。嗯,你介意我编辑你的答案来证明我的想法吗?
    【解决方案3】:

    您应该采用面向对象的方法:

    public class Country {
    
        private String name;
        private int medals;
    
        //getters/setters/constructors
    
    }
    

    然后就变得简单了:

    List<Country> countries = new ArrayList<>();
    
    //when you want to reference/print those:
    for (Country c : countries) {
        System.out.println(String.format("%s, %d medals(s)", c.getName(), c.getMedals()));
    }
    

    【讨论】:

      【解决方案4】:

      我会使用LinkedHashMap 来按国家/地区汇总奖牌:

      //List the grand total of medals for each country...display name only once
      public static void listCountryMedals(String[] country, int[] totalMedals) {
          final Map<String, Integer> map = new LinkedHashMap<String, Integer>();
      
      
          for (int i = 0; i < country.length; i++) {
              if (!map.containsKey(country[i]))
                  map.put(country[i], 0);
              map.put(country[i], map.get(country[i]) + totalMedals[i]); 
          }
      
          for (final Entry<String, Integer> entry : map.entrySet()) {
              System.out.println(entry.getKey() + ", " + entry.getValue() + " medal(s)");           
          }
      }
      

      与经典的HashMap 不同,LinkedHashMap 在迭代时将保留键顺序。您的国家/地区目前似乎已排序,因此您可能希望在打印时保持此顺序。

      【讨论】:

        【解决方案5】:

        如下改变你的方法。

        public static void listCountryMedals(String[] country, int[] totalMedals) {
        
             //Map to hold the conuntry anme and medal count pair
             Map<String,Integer> countryNameToMedalCountMap= new HashMap<String,Integer>();
        
              for (int i = 0; i < country.length; i++) {           
                 if(countryNameToMedalCountMap.get(country[i]) == null) {
                     countryNameToMedalCountMap.put(country[i],totalMedals[i]);
                 } else {
                     int count = map.get(country[i]);
                     countryNameToMedalCountMap.put(country[i],count+totalMedals[i];
                }
             }
        
              //Print the map
              for(String counrty : countryNameToMedalCountMap.keySet()) {
                  System.out.println(country+" "+ countryNameToMedalCountMap.get(country)+" medal(s).");
              }
        }
        

        注意:使用这种方法,国家名称将区分大小写。如果您想要不区分大小写,则必须设置一些机制。就像总是将地图键转换为小写并在查找时做同样的事情

        【讨论】:

          【解决方案6】:

          您可以使用地图来存储这些信息,国家为键,奖牌数为值。

          public static void listCountryMedals(String[] country, int[] totalMedals) 
          {
              Map<String, Integer> countryMedalMap = new LinkedHashMap<String, Integer>();
              for (int i = 0; i < country.length; i++) 
              {
                  String countryName = country[i];
                  /**
                   * If the country is already in the map, get the number of medal and add it up with value 
                   * from totalMedals array for that country. Then put it back to map with the new medal count.
                   */
                  if(countryMedalMap.containsKey(countryName))
                  {
                      int medalCount = countryMedalMap.get(countryName) + totalMedals[i];
                      countryMedalMap.put(countryName, medalCount);
                  }
                  /**
                   * If the country is not in the map, put it into map with its medal count.
                   */
                  else
                  {
                      countryMedalMap.put(countryName, totalMedals[i]);
                  }
              }
          
              printMap(countryMedalMap);
          }
          
          /**
           * Print the map
           * 
           * @param map
           */
          public static void printMap(Map<String, Integer> map)
          {
              for (String countryName : map.keySet())
              {
                  System.out.println(String.format("%s, %s medal(s)", countryName, map.get(countryName)));
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多