#Ways of finding X, Y, ... in a stack of CSV lines.

1 messages · Page 1 of 1 (latest)

light kayak
#

Hello, this is my first post!
I'm a CS student and I've been reading this server a lot to learn. 🙂

I was thinkering about this specific MOOC problem and I wasn't able to come up with another solution for this.

Each time the chosen team's name is found in a line, it sums up as game played (countGames).
Then, based on it's position on the line ([0] or [1]), it sum up in countWin or countLose.

Scanner scanner = new Scanner(System.in);
// File:
String fileName = scanner.nextLine();
int countGames = 0;
int countWin = 0;
int countLose = 0;
try(Scanner csvFile = new Scanner(Paths.get(fileName))){
  // Chosen Team to search:
    String inputTeam = scanner.nextLine();
    while(csvFile.hasNextLine()){
    String[] csvLine = csvFile.nextLine()
                              .split(",");
  // Team x and y score indexes will always be i+numOfTeams;
    String team1 = csvLine[0];
    String team2 = csvLine[1];
    int scoreTeam1 = Integer.parseInt(csvLine[2]);
    int scoreTeam2 = Integer.parseInt(csvLine[3]);

    if(team1.equals(inputTeam)){
        countGames++;
        if(scoreTeam1 > scoreTeam2){
            countWin++;
        }else {
            countLose++;
          }
      }

      if(team2.equals(inputTeam)){
          countGames++;
          if(scoreTeam2 > scoreTeam1){
              countWin++;
          }else{
              countLose++;
          }
     }
}catch(Exception e){
    ...
}

csv example:

Foo,Bar,5,9
Baz,Foo,10,5
Baz,Bar,20,9

I feel like this solution is ugly.
Plus, if there were more than 2 options to search in each line, it would be even more nested and ugly. In that scenario I could use switch, but it feels like it's still not the best solution.

What do you guys think, and how would you guys deal with this problem in order to bring up a cleaner solution?

Thanks for reading, wish everyone a great day. ❤️

amber masonBOT
#

<@&987246717831381062> please have a look, thanks.

drifting thistle
# light kayak Hello, this is my first post! I'm a CS student and I've been reading this server...
  • Probably shouldn't put the String inputTeam = scanner.nextLine(); inside the try block, as that would eat up any exception that occurred during the input section, also it is a little weird to read, cause it somewhat implies that you can only ask for the team after you've already opened the file, as if that somehow depended on it... probably not what anyone else would think, but I certainly got confused because of this 🐒
  • Also catch (Exception e) isn't good, you should always only catch the specific exceptions you want to catch, in this case an IOException.
drifting thistle
light kayak
light kayak
drifting thistle
#

also it's just generally expensive to have stuff in try clauses (performance wise)

drifting thistle
light kayak
light kayak
# drifting thistle Why would you ever have that? What kind of game would that be where there's more...

I agree, in this Team problem wouldn't be a thing. But I mean in another kind of problem with almost this same specification. (Searching X name that lie in different positions through a stack of csv lines)

I reason about this, because I couldn't think of another solution, that would be reusable in other domain.

Do you think it's a valid thing to be reasoning about when it comes to problem solving?

light kayak
native harness
drifting thistle
#

ah shit, accidently hit delete

amber masonBOT
# drifting thistle

I uploaded your attachments as Gist. This makes them more accessible, for example to mobile users.

drifting thistle
#

It's not really faster as in less code that needs to be written, but it's definetly more reusable for future stuff, like e.g. now you have an easy access to the game data of all games by just calling .readGameData(fileName)

#

Forgive me for the dull function name that is g

#

Btw, we could shorten the code by quiet a lot by removing classes/methods that aren't technically required, because we could also incorporate them into the lambda passed to the .reduce function, but that would become very unreadable rather quick

native harness
#

Something like this?

public class SportsStatistics {
    private record Game(String aTeam, String bTeam, int aPoints, int bPoints) { }
    private enum Result { NONE, WIN, LOSS }

    private static Result toResult(Game game, String team) {
        if (team.equals(game.aTeam())) {
            return game.aPoints() > game.bPoints() ? Result.WIN : Result.LOSS;
        } else if (team.equals(game.bTeam())) {
            return game.aPoints() < game.bPoints() ? Result.WIN : Result.LOSS;
        } else {
            return Result.NONE;
        }
    }

    private static List<Game> readGames(String filename) throws IOException {
        try (final Stream<String> lines = Files.lines(Path.of(filename))) {
            return lines
                .map(line -> line.split(","))
                .map(parts -> new Game(parts[0], parts[1], Integer.parseInt(parts[2]), Integer.parseInt(parts[3])))
                .toList();
        }
    }

    public static void main(String... args) throws IOException {
        String filename = System.console().readln("Filename: ");
        List<Game> games = readGames(filename);
        String team = System.console().readln("Team: ");

        Map<Result, Long> results = games.stream()
            .map(game -> toResult(game, team))
            .collect(Collectors.groupingBy(
                r -> r,
                () -> new EnumMap<>(Result.class),
                Collectors.counting()));

            long wins = results.getOrDefault(Result.WIN, 0L);
            long losses = results.getOrDefault(Result.LOSS, 0L);
                        
            System.out.println("Games: " + (wins + losses));
            System.out.println("Wins: " + wins);
            System.out.println("Losses: " + losses);
    }
}
light kayak
#

Thank you so much guys both of your solutions made me really happy.
Had a hard time reading the codes because of my lack of experience, but I came up with some notes

  • Never putting a Scanner inside a try block (always avoiding Scanner itself)

  • Class to handle GameData Obs: Not using constructor 1 (old solution) to handle lines, mapped instead.

  • divide-and-conquer, splitting functionalities through classes.

  • Not using Scanner to handling file, both of you used a Stream of csv GameData objects or a List of Game objects as readGameData/readGames with and a possible output being a IOException

  • enum instead of instance variable for GameResult

  • filter, map, reduce to filter and add the score for each team of searchTeams at a time. That chaining ensure that it will always be the correct input team.

  • record Game working as something like a C struct?

  • readGames handling the csv lines to a list of games (parts[0],[1]...)

  • this is so cool xD String Foo = System.console().readln("Bar");

  • noted that Collectors demand Long.

I thank both of you again for sharing these and for the time. ❤️
There's many precious techniques here that will be much of a help for the way I think about structuring and handling data in my code.
Even though I can't reproduce the same code by now, I will definitely be looking again at both your codes to improve. (:

native harness
#

A record is a class that extends Record. They are immutable, contain only the components declared in the record header, and have auto-generated accessors for the components, equals, hashCode and toString.

When nested inside another class or method they are always static classes.

Scanner is not bad for the file reading, but in this case it was convenient to handle the lines of the file as a Stream, and Files.lines(Path) given you an efficient stream of lines with no extra effort. This Stream must be closed though (as a file is attached), and wrapping it in a try-with-resources ensures that it will be closed even if an error occurs.

amber masonBOT
#

@light kayak

Your question has been closed due to inactivity.

If it was not resolved yet, feel free to just post a message below
to reopen it, or create a new thread.

Note that usually the reason for nobody calling back is that your
question may have been not well asked and hence no one felt confident
enough answering.

When you reopen the thread, try to use your time to improve the quality
of the question by elaborating, providing details, context, all relevant code
snippets, any errors you are getting, concrete examples and perhaps also some
screenshots. Share your attempt, explain the expected results and compare
them to the current results.

Also try to make the information easily accessible by sharing code
or assignment descriptions directly on Discord, not behind a link or
PDF-file; provide some guidance for long code snippets and ensure
the code is well formatted and has syntax highlighting. Kindly read through
https://stackoverflow.com/help/how-to-ask for more.

With enough info, someone knows the answer for sure 👍

amber masonBOT
#

@light kayak

Your question has been closed due to inactivity.

If it was not resolved yet, feel free to just post a message below
to reopen it, or create a new thread.

Note that usually the reason for nobody calling back is that your
question may have been not well asked and hence no one felt confident
enough answering.

When you reopen the thread, try to use your time to improve the quality
of the question by elaborating, providing details, context, all relevant code
snippets, any errors you are getting, concrete examples and perhaps also some
screenshots. Share your attempt, explain the expected results and compare
them to the current results.

Also try to make the information easily accessible by sharing code
or assignment descriptions directly on Discord, not behind a link or
PDF-file; provide some guidance for long code snippets and ensure
the code is well formatted and has syntax highlighting. Kindly read through
https://stackoverflow.com/help/how-to-ask for more.

With enough info, someone knows the answer for sure 👍

amber masonBOT
#

@light kayak

Your question has been closed due to inactivity.

If it was not resolved yet, feel free to just post a message below
to reopen it, or create a new thread.

Note that usually the reason for nobody calling back is that your
question may have been not well asked and hence no one felt confident
enough answering.

When you reopen the thread, try to use your time to improve the quality
of the question by elaborating, providing details, context, all relevant code
snippets, any errors you are getting, concrete examples and perhaps also some
screenshots. Share your attempt, explain the expected results and compare
them to the current results.

Also try to make the information easily accessible by sharing code
or assignment descriptions directly on Discord, not behind a link or
PDF-file; provide some guidance for long code snippets and ensure
the code is well formatted and has syntax highlighting. Kindly read through
https://stackoverflow.com/help/how-to-ask for more.

With enough info, someone knows the answer for sure 👍

rose girder
# native harness A record is a class that extends [Record](<https://docs.oracle.com/en/java/javas...

I would never use the first sentence to describe what a record is, the implementation is irrelevant and might even lead people to write class Something extends Record {...}
A record is a class whose purpose is to be a carrier of data, so Java made this task simpler by only requiring us to declare the fields we want to store - and it would take care of the rest(constructor, getters, equals and hashcode).

native harness
#

In that it's not a struct. You could argue that a value record is close in concept to a struct in that the runtime is likely to represent it like one in some cases (also possible with a normal record, but far less likely).

#

It was a response to...

record Game working as something like a C struct?