【问题标题】:Error in sorting two corresponding arrays对两个对应数组进行排序时出错
【发布时间】:2016-03-12 20:59:17
【问题描述】:

我正在尝试制作一个概率结果模拟器,其中信息来自 .csv 文件。创建了两个 ArrayList,然后将信息和结果放入这些 ArrayList。 Double ArrayList 包含 String ArrayList 中每个对应的两个团队的 Confidence Ratings。

Example: 
Double ArrayList:  25, 22, 50
String ArrayList: Atlanta, Michigan, NY, Detroit

Atlanta and Michigan would correspond to 25, NY and Detroit would correspond to 22.

我已经制作了程序,对置信度双倍的 ArrayList 进行了排序,但团队 String ArrayList 没有。 这是排序前的两个 ArrayList:

[1.0, 7.0, 8.0, 1.0, 10.0, 2.0, 4.0, 3.0, 1.0, 1.0, 9.0, 1.0, 3.0, 6.0, 0.0, 16.0]
[Green Bay, [Detroit, NY Jets, [NY Giants, [St. Louis, Arizona, [Tampa Bay, Atlanta, [Minnesota, Seattle, Houston, [Buffalo, [Miami, Baltimore, Cincinnati, [Cleveland, Jacksonville, [Tennessee, SF, [Chicago, Denver, [San Diego, KC, [Oakland, Carolina, [New Orleans, [New England, Philly, [Pittsburgh, Indy, [Washington, Dallas]

这两个列表整理出来后是这样的:

[16.0, 10.0, 9.0, 8.0, 7.0, 6.0, 4.0, 3.0, 3.0, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0]
[[NY Giants, [Cleveland, Jacksonville, Seattle, [Cleveland, [St. Louis, Houston, Arizona, [Buffalo, [NY Giants, [Cleveland, [Cleveland, Baltimore, [Miami, Atlanta, [NY Giants, Atlanta, [Tennessee, SF, [Chicago, Denver, [San Diego, KC, [Oakland, Carolina, [New Orleans, [New England, Philly, [Pittsburgh, Indy, [Washington, Dallas]

信心评级成功地按降序排序,但团队不对应各自的评级。事实上,同一个团队被多次复制。我如何解决这个问题并让我的所有团队都对应于他们的适当评级? (sortArrays() 方法是进行排序操作的地方)。

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.layout.*;
import javafx.scene.control.*;
import javafx.stage.FileChooser;
import javafx.geometry.*;
import java.util.*;
import java.io.*;

public class POS extends Application
{
   private ArrayList<Double> confidenceList = new ArrayList<>();
   private ArrayList<String> cityList = new ArrayList<>();
   private BorderPane pane = new BorderPane();
   private Button runBtn = new Button("Run");
   @Override
   public void start(Stage stage)
   {


      VBox vBox = new VBox(20);
      vBox.setPadding(new Insets(15));
      Button selectBtn = new Button("Select File");
      selectBtn.setStyle("-fx-font: 22 arial; -fx-base: #b6e7c9;");
      vBox.getChildren().add(selectBtn);

      selectBtn.setOnAction(e->
      {
         FileChooser fileChooser = new FileChooser();
         fileChooser.setTitle("Open Resource File");
         FileChooser.ExtensionFilter extFilter = 
                        new FileChooser.ExtensionFilter("TEXT files (*.csv)", "*.CSV", ".xlsv", ".XLSV");
                fileChooser.getExtensionFilters().add(extFilter);
         File file = fileChooser.showOpenDialog(stage);

            run(file);


      });

      RadioButton weekBtn = new RadioButton("Current Week");  
      RadioButton seasonBtn = new RadioButton("Entire Season");

      runBtn.setStyle("-fx-font: 22 arial; -fx-base: #b6e7c9;");


      weekBtn.setSelected(true);
      seasonBtn.setDisable(true);
      vBox.getChildren().add(weekBtn);
      vBox.getChildren().add(seasonBtn);
      vBox.getChildren().add(runBtn);

      pane.setLeft(vBox);
      Scene scene = new Scene(pane, 500, 200);
      stage.setScene(scene);
      stage.setTitle("POS");
      stage.show();
   }
   public void run(File file)
   {
      runBtn.setOnAction(e->
      {
         try
         {
            Scanner input = new Scanner(file);
            input.nextLine(); 
            sortFile(file, input);

            input.close();
         }

         catch (InputMismatchException ex)
         {
            System.out.println("Error you seem to have typed the wrong type of file");
         }
         catch(IOException ex)
         {
            System.out.println("Error, file could not be found");
         }


      });
   }
   public void sortFile(File file, Scanner input)
   {
      if (!input.hasNext())
      {
         sortArrays(confidenceList, cityList);
      }
      else
      {
      String strList = Arrays.toString(input.nextLine().split("\t"));
      String[] arrList = strList.split(",");

      int homeRank = Integer.parseInt(arrList[1]);

      int roadRank = Integer.parseInt(arrList[6]);
      Random r = new Random();

      int lowestTeamRank = Math.abs(homeRank - roadRank);

      double numForHomeTeam = 0;
      double numForRoadTeam = 0;
      if (homeRank < roadRank)
      {
         numForHomeTeam = ((r.nextInt(lowestTeamRank) - r.nextInt(2)) + (getLastGameOutcome(arrList[4])* r.nextInt(3))) - getWinPct(arrList[2], arrList[3]);

         numForRoadTeam = ((r.nextInt(roadRank) + r.nextInt(2)) + (getLastGameOutcome(arrList[9])* r.nextInt(3))) - getWinPct(arrList[7], arrList[8]);
      }

      else if (homeRank > roadRank)
      {
         numForHomeTeam = ((r.nextInt(homeRank) - r.nextInt(2)) + (getLastGameOutcome(arrList[4])* r.nextInt(3))) - getWinPct(arrList[2], arrList[3]);

         numForRoadTeam = r.nextInt(lowestTeamRank) - r.nextInt(2) + getLastGameOutcome(arrList[9])* r.nextInt(3) - getWinPct(arrList[7], arrList[8]);
      }



      double confidenceRate = Math.round(Math.abs(numForHomeTeam - numForRoadTeam));
      confidenceList.add(confidenceRate);
      if (numForHomeTeam < numForRoadTeam)
      {
          cityList.add(arrList[0]);
          cityList.add(arrList[5]);
      }
      else if (numForHomeTeam > numForRoadTeam)
      {
         cityList.add(arrList[5]);
         cityList.add(arrList[0]);
      }
      else
      {
         cityList.add(arrList[0]);
         cityList.add(arrList[5]);
      }

      sortFile(file, input);
      }
   }

   public int getLastGameOutcome(String lastGame)
   {
      if (lastGame.charAt(0) == 'W')
      {
         return (int)(Math.random() * 3);
      }

      else
      {
         return (int)(Math.random() * -3);
      }  
   }

   public double getWinPct(String wins, String losses)
   {
       double newWins = Double.parseDouble(wins);
       double newLosses = Double.parseDouble(losses);
       return newWins / (newWins + newLosses);
   } 

   public void sortArrays(ArrayList<Double> doubleArray, ArrayList<String> stringArray)
   {
      System.out.println(doubleArray);
      System.out.println(stringArray);
      for (int i = 0; i < doubleArray.size(); i++)
      {
         for (int j = 0; j < doubleArray.size(); j++)
         {
            if (doubleArray.get(j).compareTo(doubleArray.get(i)) < 1)
            {
               double tempDouble = doubleArray.get(j);
               doubleArray.set(j, doubleArray.get(i));
               doubleArray.set(i, tempDouble);

               String tempString = stringArray.get(j);
               String tempString2 = stringArray.get(j + 1);
               stringArray.set(j, stringArray.get(i));
               stringArray.set(j + 1, stringArray.get(i + 1));
               stringArray.set(i, tempString);
               stringArray.set(i + 1, tempString2);
            }
         }
      }

      System.out.println(doubleArray);
      System.out.println(stringArray);
   } 

}

【问题讨论】:

    标签: java sorting arraylist javafx


    【解决方案1】:

    我不会拥有两个独立的数据结构,而是将它们组合成一个简单的 Java 对象列表,该对象表示数据的基本含义。

    例如,保持信心评级和团队:

    public class TeamConfidence implements Comparable<TeamConfidence> {
      private String team;
      private double confidence;
    
      public TeamConfidence(String team, double confidence) {
        this.team = team;
        this.confidence = confidence;
      }
    
      @Override
      public int compareTo(TeamConfidence other) {
          if(other == this) { 
            return true;
          } else if (other == null ) {
            return false;
          } else {
            return Double.compare(confidence, other.confidence);
          }
      }
    
      // include getters and setters, maybe a constructor
    }
    

    由于它实现了Comparable 接口,您可以使用Collections.sort 调用进行置信度排序:

    List<TeamConfidence> teams = new ArrayList<>();
    // populate list
    Collections.sort(teams);
    // list is now ordered by confidence, and still retains the relation between 
    // the team name and the confidence level
    

    这是一个简化的示例,说明我们将如何实现这一点。

    假设我们有一个最小的数据集,使用您的原始示例,丹佛和巴尔的摩作为一些较低的异常值:

    | Team      | Confidence |
    | Atlanta   | 25         |
    | Michigan  | 25         |
    | Detroit   | 22         |
    | NY        | 22         |
    | Denver    | 13         |
    | Baltimore | 1          |
    

    注意,我在上面的 TeamConfidence 类中添加了一个构造函数,用于演示目的。

    我们首先要为自己创建一组 TeamConfidence 对象。作为示例,我们将在此处手动创建它们,但您可以针对从文件、数据库或其他数据源进行读取进行调整。

    我们还将在List 中添加对象。

    // declare a list to hold the TeamConfidence objects
    List<TeamConfidence> teams = new ArrayList<>();
    
    // populate the list
    teams.add(new TeamConfidence("Detroit", 22.0));
    teams.add(new TeamConfidence("Atlanta", 25.0));
    teams.add(new TeamConfidence("Baltimore", 1.0));
    teams.add(new TeamConfidence("Michigan", 25.0));
    teams.add(new TeamConfidence("NY", 22.0));
    teams.add(new TeamConfidence("Denver", 13.0));
    

    此时,我们有一个团队列表。现在我们打电话给sort

    Collections.sort(teams);
    

    现在我们的名单已经按顺序排列了我们的团队。根据您在TeamConfidence 中实现compareTo 方法的方式,这将导致先变小,或者先变大。 (要交换订单,乘以-1;例如-1*Double.compare(confidence, other.confidence);

    假设这个比较对象被实现为先小而后,我认为是这样(但我想不起来),我们的列表将按如下顺序排列:

    [(Baltimore, 1.0), (Denver, 13.0), (NY, 22.0), (Detroit, 22.0), (Atlanta, 25.0), (Michigan, 25.0)]
    

    请注意,由于我们的compareTo 方法只考虑了置信度,因此在置信度范围内没有排序;所以纽约和底特律相邻,但不能保证纽约会始终排在底特律之前。


    根据下面的 cmets,最好让模型如下:

    public class TeamConfidence implements Comparable<TeamConfidence> {
      private String winner;
      private String loser;
      private double confidence;
    
      public TeamConfidence(String winner, String loser, double confidence) {
        this.winner = winner;
        this.loser = loser;
        this.confidence = confidence;
      }
    
      @Override
      public String toString() {
        return "(" + confidence + ", " + winner + ", " + loser ")";
      }
    
      @Override
      public int compareTo(TeamConfidence other) {
          if(other == this) { 
            return true;
          } else if (other == null ) {
            return false;
          } else {
            return Double.compare(confidence, other.confidence);
          }
      }
    }
    

    现在,当您按置信度排序时,列表中的每个元素都将指示获胜者和失败者。

    数据:

    | Winner  | Loser     | Confidence |
    | Atlanta | Michigan  | 25         |
    | NY      | Detroit   | 22         |
    | Denver  | Baltimore | 13         |
    

    代码:

    List<TeamConfidence> teams = new ArrayList<>();
    
    // populate the list
    teams.add(new TeamConfidence("Atlanta", "Michigan", 25.0));
    teams.add(new TeamConfidence("NY", "Detroit", 22.0));
    teams.add(new TeamConfidence("Denver", "Baltimore", 13.0));
    
    Collections.sort(teams);
    

    结果:

    // (confidence, winner, loser)
    [(13.0, Denver, Baltimore), (22.0, NY, Detroit), (25.0, Atlanta, Michigan)]
    

    【讨论】:

    • 为了让我同时添加球队(字符串)和信心评级(双打),我需要有两个构造函数,对吗?另外,我需要添加信心,基于奖金的正确团队顺序,然后排序。我只需要写 Collections.sort(teams);它会根据信心对其进行排序吗?您能否根据我的程序为我提供一些有关如何实现此功能的详细步骤,因为我在理解我需要做什么来获得结果时遇到了一些麻烦。谢谢:)
    • 嗨,@Bytes。我用一个例子更新了我的答案。我希望能澄清一些事情。
    • 一个信心等级总是等同于两支球队互相对抗。所以总会有两支球队的信心等级相同。没有一支球队有一个信心等级。示例:假设亚特兰大和底特律比赛,算法(基于 .csv 文件中的数据)将确定他们的置信度等级。获胜者(亚特兰大)将排在失败者(底特律)之前。所以列表如下:信心、赢家、输家、信心、赢家、输家
    • 该模型可能应该被称为ConfidenceRating 而不是TeamConfidence。 :) 我已经用一个示例更新了答案,说明如何将两个团队存储在同一模型中的“赢家”和“输家”插槽中。但这几乎都归结为Comparable 接口的实现,它定义了Collections.sort 将如何做它的事情。
    • 几乎可以工作了!该列表以递增顺序显示,而不是递减。我要先高数,后低数,可以吗?我想将此数据显示为 GridPane 网格,其中有三列(信心、赢家、输家)。如何将 GridPane 中的数据从置信度的递增顺序循环到递减顺序?
    猜你喜欢
    • 2011-04-23
    • 2014-06-13
    • 1970-01-01
    • 2016-07-26
    • 1970-01-01
    • 2013-07-20
    • 2021-10-15
    相关资源
    最近更新 更多