Basic Java programming with Multiple ArrayLists - java

In the following code, I have taken in a list of 5 student names, and loading them in an ArrayList of type String.
import java.util.Scanner;
import java.util.ArrayList;
public class QuizAverage
{
public static void main( String[] args ) {
final int NAMELIMIT = 5 ;
final int QUIZLIMIT = 5 ;
ArrayList<String> sNames = new ArrayList<String>();
ArrayList<String> sFamily = new ArrayList<String>();
Scanner in = new Scanner(System.in);
//Load the 5 names of the students in the arraylist
for(int i = 1; i<=NAMELIMIT; i++)
{
String[] input = in.nextLine().split("\\s+");
sNames.add(input[0]);
sFamily.add(input[1]);
}
System.out.println("Name: ");
System.out.println();
for(int i=0; i<NAMELIMIT; i++)
{
System.out.println("Name: " +sNames.get(i) + " " + sFamily.get(i));
}
System.out.println();
}
}
However, now I am trying to add to the code a part that reads in marks for 5 quizes for each student and loads the quiz marks in An ArrayList of type Integer
So I know I need to use
ArrayList<Integer> quizMarks = readArrayList(readQuiz.nextLine());
and then pass it on to this code which takes the quiz marks and weights them out of 15 instead of 100
public static ArrayList<Integer> readArrayList(String input)
{
ArrayList<Integer> quiz = new ArrayList<Integer>();
int i = 1;
while (i <= QUIZLIMIT)
{
if (readQuiz.hasNextInt()) {
quiz.add(readQuiz.nextInt());
i++;
} else {
readQuiz.next(); // toss the next read token
}
}
return quiz;
}
//Computer the average of quiz marks
public static void computerAverage(ArrayList<Integer>quiz)
{
double total = 0 ;
for(Integer value : quiz)
{
total = total + value;
}
total *= MAX_SCORE/100;
System.out.println("Quiz Avg: "+ total / QUIZLIMIT );
}
}
So my current code with the input:
Sally Mae 90 80 45 60 75
Charlotte Tea 60 75 80 90 70
Oliver Cats 55 65 76 90 80
Milo Peet 90 95 85 75 80
Gavin Brown 45 65 75 55 80
Gives the output
Name: Sally Mae
Name: Charlotte Tea
Name: Oliver Cats
Name: Milo Peet
Name: Gavin Brown
when the desired output is
Name: Sally Mae Quiz Avg: 10.5
Name: Charlotte Tea Quiz Avg: 11.25
Name: Oliver Cats Quiz Avg: 10.95
Name: Milo Peet Quiz Avg: 12.75
Name: Gavin Brown Quiz Avg: 9.6

As Jim said, you should store the marks and the name of the student in the same class. The reason for doing that is say going forward you want to find the marks of a particular student named Raj.
In your implementation you would have to go through the first array for find the index of the person named Raj and then go to the same index in the marks array. If there was no problem in initializing the first array but there was some problem in creating the marks array you might end up with the wrong marks.
Also if you have to add a new attribute to a student you would have to create a new array and then add one more logic to read that data.
Having a class gives you an easy way to group all the data belonging to a student.
For your problem of averaging, I'd have a class as follows
class Student {
private String name;
private Double marks;
public Student(String name, String marks) {
this.name = name;
this.marks = marks;
}
//getters setters
}
Have a list of Student
List<Student> students = new ArrayList<Student>();
After reading you will append the object to this list
students.add(new Student(name, marks));
Computing average is as follows
Double average = 0;
for(Student student: students) {
average += student.getMarks();
}
average = average / student.size();
Checkout https://docs.oracle.com/javase/tutorial/collections/streams/reduction.html for other ways to get the average.

Don't use parallel arrays. Use a Student class instead:
public class Student {
private String name;
private String family;
private List<Integer> marks = new ArrayList<>();
public Student(String name, String family)
{
this.name = name;
this.family = family;
}
// getters, setters
...
public void addMark(int mark)
{
this.marks.add(mark);
}
public void getAverage()
{
... // etc
}
}
Then store instances of this class in a single list in your main program
List<Student> students = new ArrayList<>();

You haven't called computerAverage() yet from what I see.

Related

Reading Data from a txt File in Java

I am trying to read data from a text file in Java. I want to read student names from the text file and put them into a String array which is called as "student". Also i want to read student grades. When i execute the program the output be like this:
click to see the output
Please help me. How can i read student names and grades from the text file without using Buffer or Stream or etc.?
File file = new File("StudentScores.txt");
Scanner input = new Scanner(file);
int i = 0;
while(input.hasNext()){
input.nextLine();
i++;
}
String[] student = new String[i];
while(input.hasNext()){
String name = input.next();
double grade = input.nextDouble();
System.out.println(name + " " + grade );
}
for(String a : student){
System.out.println(a);
}
StudentScores.txt Content:
John 60 70 80 90 65 75 70 89.5 75.4
Can 60 70 80 90 80 75 70 89.5 75.4
Cannot 60 -70 80 90 80 75 -70 89.5 75.4
Scanner moves only forward. First scanner part read whole file and second while(input.hasNext()) subpart will be not called. Take a look below script.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws FileNotFoundException {
File file = new File("StudentScores.txt");
List<Student> students = new ArrayList<>();
Scanner input = new Scanner(file);
while (input.hasNext()) {
String line = input.nextLine();
if (line.isEmpty()) {
break;
}
// split with spaces
String[] str = line.split(" ");
// first item is name
Student student = new Student(str[0]);
// visit rest items are grade values
for (int i = 1; i < str.length; i++) {
student.addGrade(Double.parseDouble(str[i]));
}
// add into the list
students.add(student);
}
for (Student student : students) {
System.out.println(student);
}
}
private static class Student {
private String name;
private List<Double> grades = new ArrayList<>();
public Student(String name) {
this.name = name;
}
public void addGrade(double grade) {
grades.add(grade);
}
public List<Double> getGrades() {
return grades;
}
#Override
public String toString() {
return name + ", grades=" + grades;
}
}
}
Output:
John, grades=[60.0, 70.0, 80.0, 90.0, 65.0, 75.0, 70.0, 89.5, 75.4]
Can, grades=[60.0, 70.0, 80.0, 90.0, 80.0, 75.0, 70.0, 89.5, 75.4]
Cannot, grades=[60.0, -70.0, 80.0, 90.0, 80.0, 75.0, -70.0, 89.5, 75.4]

How to get average of test scores organized into columns in a file?

The file contains the data in the following format:
Name|Test1|Test2|Test3|Test4|Test5|Test6|Test7|Test8|Test9|Test10
John Smith|82|89|90|78|89|96|75|88|90|96
Jane Doe|90|92|93|90|89|84|97|91|87|91
Joseph Cruz|68|74|78|81|79|86|80|81|82|87
Suzanne Nguyen|79|83|85|89|81|79|86|92|87|88
I am trying to find out how to get the sum of each column (Ex. Test 1 = 82 + 92 + 68 + ...) to ultimately calculate the average score for each test.
This is how I parsed the file and did the other calculations:
public class TestAverages
{
private static int[] grades;
private static int[] testTotal;
private static int N;
private static double classTotal;
public static void main(String[] args) throws FileNotFoundException
{
File input = new File("TestData.txt");
Scanner in = new Scanner(input);
parseFile(in);
}
public static void parseFile(Scanner in) throws FileNotFoundException
{
TestAverages t = new TestAverages();
in.nextLine(); //skips the first line of text in file (labels)
double classAvg =0.0;
while(in.hasNextLine())
{
String line = in.nextLine();
String[] data = line.split("\\|");
String name = data[0];
grades = new int[data.length - 1];
N = grades.length;
for(int i = 0; i < N; i++)
{
grades[i] = Integer.parseInt(data[i + 1]);
}
System.out.println(name);
System.out.println("Student Average: " + t.getStudentAvg(grades) + "%\n");
classAvg = t.getClassAvg(grades);
System.out.println("Test Average: " + t.getTestAvg(grades) + "%\n");
}
System.out.printf("\nClass Average: %.2f%%\n", classAvg );
}
public double getStudentAvg(int[] grades)
{
double total = 0.0;
double avg = 0.0;
int N = grades.length;
for(int i = 0; i < N; i++){
total += grades[i];}
avg = total / N;
return avg;
}
public double getClassAvg(int[] grades)
{
double classTotal = getStudentAvg(grades) / N;
double classAvg =0.0;
classTotal += classTotal;
classAvg = classTotal;
return classTotal;
}
}
Please excuse my formatting if it's not up to par to the standard.
My main issue at the moment is how to extract the score for each test for each student and add everything up.
The test scores for each student are being calculated. What you need are the class average and the test average.
The test averages are the average scores on each test.
The student averages are the average test scores for each student
The class averages is how the overall class did on all the tests.
Consider three tests
test1 test2 test3 student average
student1 90 80 70 240/3
student2 100 90 90 280/3
student3 80 80 90 250/3
testAvg 270/3 250/3 250/3
class avg = (270 + 250 + 250)/9 or (240+280+250)/9
So you need to read in the values in such a way so as to facilitate making the other calculations. I would recommend either a Map<String,List<Integer>> for the data where the string is the students name and the list is the test scores for each student. Or you could use a 2D int array. But you need to save the scores so you can do the column average for the test scores. Most of the work is done.
Also, two problems I noticed. You call the method getTestAvg but don't declare it and you declare the method getClassAvg but never call it.
if you already know that there are 10 test total in the file , it should be easy .
you can let int[] testTotal = new int[10]; for testTotal[0] = sum-of-first-column , testTotal[1] = sum-of-second-column and so on . . .
you can read each line in and split them with "\\|" as regex
as you are cycling through lines , let testTotal[0] += data[1] , testTotal[1] += data[2] . . . testTotal[9] += data[10] since data[0] is the name of the student .

Java file io calculating average and storing in another file

I would appreciate knowing how to tackle this type of problems. Thank you in advance.
Here is the question.
The first line of the files contains two integer numbers ;
number-of-records exam-grade
number-of-records : indicates number of the records in the file.
exam-grade : indicates the grade of the exam.
The file follows by students name and their grades.
Sample File: test1.txt
Contains four records, and the exam is out of 80. The file follows by the name and grade of the students:
4 80
Mary 65.5
Jack 43.25
Harry 79.0
Mike 32.5
You have to develop the body of following method:
public static void readWrite(String srcfileName, String dstFileName)
That reads grades of each student from srcFileName, calculates their grade percent, indicates that if student passed or failed, and finally reports the class average, number of the students passed, and number of the students failed the exam and saves the result in dstFileName.
The output file for the previous test file should be:
Mary 81.88 passed
Jack 54.06 passed
Harry 98.75 passed
Mike 40.63 failed
class average:68.83
passed: 3
failed: 1
here is the code I wrote for it,
import java.util.*;
import java.io.*;
public class Lab10Quiz {
public static void main(String[] args) throws FileNotFoundException
{
// Test cases
readWrite("test1.txt", "out1.txt");
readWrite("test2.txt", "out2.txt");
}
/** copies the content of the srcFileName into dstFileName, and add the average of the number to the end of the dstFileName
#param srcFileName : souce file name contains double numbers
#param dstFileName : destination file name
*/
public static void readWrite(String srcFileName, String
dstFileName) throws FileNotFoundException {
// Your code goes here
File output = new File(dstFileName);
PrintWriter outPut = new PrintWriter(output);
double avg = 0;
int count = 0;
double tmp = 0;
Scanner in = new Scanner(new File(srcFileName));
while (in.hasNextDouble()) {
tmp = in.nextDouble();
avg += tmp;
outPut.println(tmp);
count ++;
}
avg = avg / count;
outPut.println("Average = " + avg);
outPut.close();
}
}
This code achieves what you want
double avg = 0;
int failCounter = 0;
String[] keywords = in.nextLine().split(" ");
int studentNumber = Integer.parseInt(keywords[0]);
double examValue = Double.parseDouble(keywords[1]);
for (int i = 0; i < studentNumber; i++) {
keywords = in.nextLine().split(" ");
String studentName = keywords[0];
double studentMark = Double.parseDouble(keywords[1]);
double grade = calculateTotalGrade(studentMark, examValue);
failCounter += (hasFailed(grade) ? 1 : 0);
avg += grade;
outPut.println(String.format("%s \t\t %.2f \t\t %s", studentName, grade, hasFailed(grade) ? "failed" : "passed"));
}
avg = avg / studentNumber;
outPut.println("class average: " + avg);
outPut.println("passed: " + (studentNumber - failCounter));
outPut.println("failed: " + failCounter);
And I extracted some of the logic to below methods.
private static double calculateTotalGrade(double grade, double examValue) {
return grade * 100 / examValue;
}
private static boolean hasFailed(double grade) {
return grade < 50;
}
To answer how to tackle this type of questions:
Look for the simplest way. In this case looping for a finite iterations was easier. So I went with the for loop.
The counter is already given, No need to re-calculate it.
If you are working on a computer, write a little code and test it.
Do more questions like these. (if you go through the first chapters of this book these questions will be easy)

Printing Out Object In Java

I have a file that has the following content:
5
Derrick Rose
1 15 19 26 33 46
Kobe Bryant
17 19 33 34 46 47
Pau Gasol
1 4 9 16 25 36
Kevin Durant
17 19 34 46 47 48
LeBron James
5 10 17 19 34 47
I'm trying to put the names and then numbers for the ticket in an array in my ticket constructor, however when I instantiate my ticket object and try to display it I get the following:
Tickets: lottery$Ticket#33909752
Tickets: lottery$Ticket#55f96302
Tickets: lottery$Ticket#3d4eac69
Tickets: lottery$Ticket#42a57993
Tickets: lottery$Ticket#75b84c92
Does the problem in my constructor for ticket or is it impossible to print an array without making it a string first?
int lim = scan.nextInt();
scan.nextLine();
for(int i = 0; i < lim; i++)
{
String name = scan.nextLine();
String num = scan.nextLine();
String[] t = num.split(" ");
int[] tichold = new int[t.length];
for(int j = 0; j < t.length; j++)
{
tichold[j] = Integer.parseInt(t[j]);
}
Ticket ticket = new Ticket(name, tichold);
System.out.println("Ticket: " + ticket);
}
scan.close();
}
public static class Ticket
{
public String name;
public int[] tarray;
public Ticket(String name, int[] tarray)
{
this.name = name;
this.tarray = tarray;
}
}
You need to provide toString method for it. Here is sample, which you can use:
#Override
public String toString() {
return "Ticket{" +
"name='" + name + '\'' +
", tarray=" + Arrays.toString(tarray) +
'}';
}
In order to accomplish that you need to write an overiding toString method and write in there want you want.
public String toString(){
return //whatever you need goes here and will be printed when you try and
//print the object
}
You must override the toString method which is inherited from the Object class:
#Override
public String toString(){
return //Enter the format you require
}
Remember ticket is a reference variable so when you print it out, you will get the hashcode along with the name of the class of which the object is an instance.

How to sort list from least to greatest [duplicate]

This question already has answers here:
Sorting a collection of objects [duplicate]
(9 answers)
Closed 8 years ago.
Almost done with this program, but when it's sorted out the weight is being arranged to from least to greatest, which is correct. The only problem is that the name and age associated with the weight are not sorted with the weight.
for example
mike 25 180
jen 36 105
sam 22 120
I should get
jen 36 105
sam 22 120
mike 25 180
but I get
mike 25 105
jen 36 120
sam 22 180
import java.util.*;
import java.util.ArrayList;
import java.util.List;
public class Lab0 {
public static void main(String[] args) {
//Scanner and variables
Scanner keyboard = new Scanner (System.in);
String name = "";
int age;
double weight;
int number;
//Creates list for name, age, and weight
ArrayList<String> Name = new ArrayList<String>();
ArrayList<Integer> Age = new ArrayList<Integer>();
ArrayList<Double> Weight = new ArrayList<Double>();
System.out.println("Enter the information needed.");
//Ask user to enter information needed
while (true){
System.out.print("Enter last name: ");
name = keyboard.nextLine();
if(name.equalsIgnoreCase("FINISHED")){
break;
}
else {
Name.add(name);
System.out.print("Enter age: ");
age = keyboard.nextInt();
Age.add(age);
System.out.print("Enter weight: ");
weight = keyboard.nextDouble();
Weight.add(weight);
keyboard.nextLine();
System.out.println("==========================================\n");
}
}
//new list to sort weight and age and name
ArrayList<String> NameList = Name;
ArrayList<Integer> AgeList = Age;
ArrayList<Double> WeightList = Weight;
Collections.sort(Weight);
for(int i=0; i<Weight.size(); i++){
for (int j=0; j<Weight.size(); j++){
if(WeightList.get(j) == Weight.get(i)){
Name.set(j, NameList.get(i));
Age.set(j, AgeList.get(i));
}
else;
}
}
//prints out information entered
for (int k=0; k<Weight.size(); k++){
System.out.println("Name: " + Name.get(k) + " Age: " + Age.get(k)
+ " weight: " + Weight.get(k));
}
while (true){
System.out.println("=============================================");
System.out.print("Enter a last name that you listed: ");
String Search = keyboard.next();
int index = Name.indexOf(Search);
if (index >=0){
System.out.println("Age: " + Age.get(index));
System.out.println("Weight: " + Weight.get(index));
}
else if(Search.equalsIgnoreCase ("DONE")){
System.exit(0);
}
else{
System.out.println("NOT FOUND");
}
}
}
}
The problem is, that the relation is loosing between the single-informations.
A person is a tripel like (name, age, weight).
You have three lists and after sorting the list with weights, you're want to concatenate the single-informations.
That is the problem-section of your code:
ArrayList<String> NameList = Name;
ArrayList<Integer> AgeList = Age;
ArrayList<Double> WeightList = Weight;
Collections.sort(Weight);
for(int i=0; i<Weight.size(); i++){
for (int j=0; j<Weight.size(); j++){
if(WeightList.get(j) == Weight.get(i)){
Name.set(j, NameList.get(i));
Age.set(j, AgeList.get(i));
}
else;
}
}
Your first problem is:
If two or more persons having the same weight, you're not find a clearly relation. (Not the topic of your question, but a problem.)
Your secound problem is:
(If all weights are different.)
Collections.sort(Weight);
This method sorts the list 'Weight'.
But it is the same list with the name 'WeightList '.
You're copy the reference.
You shold clone the list first, bevore you're use sort.
And you need to change i and j in 'Name.set(...)' and 'Age.set(...)'.
This should help:
ArrayList<String> NameList = (ArrayList<String>) Name.clone();
ArrayList<Integer> AgeList = (ArrayList<Integer>) Age.clone();
ArrayList<Double> WeightList = (ArrayList<Double>) Weight.clone();
Collections.sort(Weight);
for (int i = 0; i < Weight.size(); i++) {
for (int j = 0; j < Weight.size(); j++) {
if (WeightList.get(j) == Weight.get(i)) {
Name.set(i, NameList.get(j));
Age.set(i, AgeList.get(j));
}
else
;
}
}
I think that's the answer for your problem.
In addition:
You should think about 'ChrisForrence' comment of your qurestion.
It is better using a class for person which implements the interface 'Comparable'.
You should use comparators in my opinion.
That is the general method for getting flexibility.

Categories

Resources