Tobia Zamò
Tobia Zamò

Reputation: 37

Calculating Average from a list of students taken from a .txt file

I have a separated .txt file in which there is a list of "students" with their own mark on the side that goes from 0 to 10, here is an example on how the .txt looks like:

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

What I want to do is calculating the Average of each student (expressed in double) so that the output would look like this:

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

Here is what I've come up with, for now I've only managed to use Properties to list the student names without repetition, but the number shown on the side of each one of them is obviously the last one the program finds.
I've included it on a button actionlistener as I'm implementing a GUI, by pressing the button the output shown above is append in a TextArea:

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

I was thinking to use Collectors to calculate the average, but I actually don't know how to implement it...

Any help is appreciated!

Thanks in advance!

Upvotes: 3

Views: 1104

Answers (1)

ricky3350
ricky3350

Reputation: 1738

The way I like to do this kind of thing is using Maps and Lists.

To read the lines from the file, I'm fond of the nio way of reading, so I would do

List<String> lines = Files.readAllLines(Paths.get("RegistroVoti.txt"));

Then, you can make a HashMap<String,List<Integer>>, which will store each person's name and a list of the numbers associated with them:

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

Then, using a for each loop, go through each of the lines and add each number to the hash map:

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

Then, you can go through each entry in the map and calculate the average of the associated list:

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

(Note that this is a Java 8 stream solution; you could just as easily write a for loop to calculate it in earlier versions)

For more information on some of the things I've used, see:

Hope this helps!

Edit A complete solution:

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

Upvotes: 4

Related Questions