从 .txt 文件中获取学生列表并计算平均值

3

我有一个分离的 .txt 文件,其中包含一个“学生”列表和他们的分数(从 0 到 10),以下是 .txt 文件的示例:

Mark 2
Elen 3
Luke 7
Elen 9
Jhon 5
Mark 4
Elen 10
Luke 1
Jhon 1
Jhon 7
Elen 5
Mark 3
Mark 7

我想要做的是计算每个学生的平均分(以 double 形式表示),以便输出如下:

Mark: 4.0
Elen: 6.75
Luke: 4.0
Jhon: 4.33

这是我现在想到的,目前我只能使用 Properties 列出学生姓名而不重复,但每个人旁边显示的数字显然是程序找到的最后一个。
我已将它包含在按钮动作侦听器中,因为我正在实现 GUI,在按下按钮时,上面显示的输出会在 TextAreaappend

 b1.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent d) {

   try {
      File file = new File("RegistroVoti.txt");
      FileInputStream fileInput = new FileInputStream(file);
      Properties properties = new Properties();
      properties.load(fileInput);
      fileInput.close();

      Enumeration enuKeys = properties.keys();
      while (enuKeys.hasMoreElements()) {
        String key = (String) enuKeys.nextElement();
        String value = properties.getProperty(key);
        l1.append(key + ": " + value + "\n");
      }
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
});

我在考虑使用Collectors来计算平均值,但实际上我不知道如何实现它...
非常感谢您的帮助!
提前致谢!

为了将来的使用,请学习集合。http://www.tutorialspoint.com/java/java_collections.htm - UDID
4
你可以使用一个“HashMap”来存储键值对......你的键可以是学生的姓名,值可以是成绩的“ArrayList”。读取文件后,你可以遍历“HashMap”,并基于分数的“ArrayList”为每个学生计算平均分数。 - brso05
使用属性将不起作用,因为属性“Mark”只会有一个值。 - Grayson
1个回答

4
我喜欢使用MapList来处理这种情况。
为了读取文件中的行,我喜欢使用nio方式进行读取,所以我会这样做:
List<String> lines = Files.readAllLines(Paths.get("RegistroVoti.txt"));

然后,你可以创建一个 HashMap<String,List<Integer>>,它将存储每个人的姓名和与他们相关的数字列表:
HashMap<String, List<Integer>> studentMarks = new HashMap<>();

然后,使用 for each 循环,遍历每一行并将每个数字添加到哈希映射表中:
for (String line : lines) {
    String[] parts = line.split(" ");
    if (studentMarks.get(parts[0]) == null) {
        studentMarks.put(parts[0], new ArrayList<>());
    }
    studentMarks.get(parts[0]).add(Integer.parseInt(parts[1]));
}

然后,您可以遍历地图中的每个条目并计算相关列表的平均值:
for (String name : studentMarks.keySet()) {
    System.out.println(name + " " + studentMarks.get(name).stream().mapToInt(i -> i).average().getAsDouble());
}

(请注意,这是一个Java 8的 stream 解决方案; 你可以很容易地写一个for循环来在早期版本中计算它)
有关我使用的一些东西的更多信息,请参见: 希望这有所帮助! 编辑完整解决方案:
b1.addActionListener(new ActionListener() {

    public void actionPerformed(ActionEvent d) {
        try {
            List<String> lines = Files.readAllLines(Paths.get("RegistroVoti.txt"));

            Map<String, List<Integer>> studentMarks = new HashMap<>();

            for (String line : lines) {
                String[] parts = line.split(" ");

                if (studentMarks.get(parts[0]) == null) {
                    studentMarks.put(parts[0], new ArrayList<>());
                }
                studentMarks.get(parts[0]).add(Integer.parseInt(parts[1]));
            }

            for (String name : studentMarks.keySet()) {
                System.out.println(name + " " + studentMarks.get(name).stream().mapToInt(i -> i).average().getAsDouble());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
});

首先,非常感谢您的回答!我所有的问题都已经成功解决,我也学到了新的东西!然而,我需要一些提示来完成另一件事情...我想在一个 TextArea 中打印一个包含 .txt 文件中每个单独投票发生次数的垂直柱状图(例如:“1”将有2个星号,“2”将有1个星号,依此类推),我已经搜索过了,但不幸的是我无法编写一个正确编译的解决方案。 - Tobia Zamò
@TobiaZamò,我很高兴能帮到你。您的请求太长了,无法在评论中回答;您最好[提出一个新问题](http://stackoverflow.com/questions/ask)(如果您还没有)。这样,人们可以发布完整的答案,您可以提出完整的问题,并附上您所尝试的内容。 - ricky3350

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接