Reputation: 69
I am practicing sorting of arrays, and I have successfully sorted a string array.
My little program allows users to enter first number of students, then the name of each one, and at last their grade of each one.
But I also want to sort the int studentGrade
array so that the grades in the printout matches the student. Here I am really stuck. See further down for more explanation down in the method: public void sortingAlgorithm
package assignment8exam;
import java.util.Scanner;
import java.util.Arrays;
/**
*
* @author Anders
*/
public class Course {
Scanner sc = new Scanner(System.in);
public void MainMenu() {
System.out.println("Enter data about a student, start by entering how many");
int numbers = sc.nextInt();// amount of student
String studentNames[] = new String[numbers];
int studentGrade[] = new int[numbers];
for (int i = 0; i < numbers; i++) {
System.out.println("Enter name of student");
Scanner name = new Scanner(System.in);
String names = name.nextLine();
studentNames[i] = names;
}
for (int j = 0; j < numbers; j++) {
System.out.println("Enter grade of student");
Scanner gradeSc = new Scanner(System.in);
int grade = gradeSc.nextInt();
studentGrade[j] = grade;
}
sortingArray(studentNames);
System.out.println("------------------------------------\n");
sortAlgorithm(studentNames, studentGrade);
System.out.println("What do you want");
System.out.println("Exit application 1");
System.out.println("Print out all names of the students 2");
System.out.println("Print out all the grades of the students 3");
System.out.println("Print out pairs consisting of “namegrade 4");
System.out.println("Search for a student - 5");
Scanner choice = new Scanner(System.in);
int order = choice.nextInt();
switch (order) {
case 1:
System.exit(1);
case 2:
PrintOutNames(numbers, studentNames);
case 3:
PrintOutGrades(numbers, studentGrade);
case 4:
PrintOutAll(numbers, studentGrade, studentNames);
case 5:
search(numbers, studentGrade, studentNames);
}
}
public static void PrintOutNames(int numbers, String studentNames[]) {
for (int i = 0; i < numbers; i++) {
System.out.println(studentNames[i]);
}
}
public static void PrintOutGrades(int numbers, int studentGrade[]) {
for (int i = 0; i < numbers; i++) {
System.out.println(studentGrade[i]);
}
}
public static void PrintOutAll(int numbers, int studentGrade[], String studentNames[]) {
System.out.println("--------------------------------------------------------\n");
for (int i = 0; i < numbers; i++) {
System.out.println("Name----> " + studentNames[i] + " grade ---> " + studentGrade[i]);
}
}
public static void search(int numbers, int studentGrade[], String studentNames[]) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter name on student you want to search on ");
String search = sc.nextLine();
for (int i = 0; i < numbers; i++) {
if (search.equals(studentNames[i])) {
System.out.println("Yes we have a student named " + studentNames[i] + " with the Grade " + studentGrade[i] + " \n ");
}
}
}
public static void sortingArray(String studentNames[]) {
Arrays.sort(studentNames);
System.out.println("-------------\n" + Arrays.toString(studentNames));
}
public static void sortAlgorithm(String studentNames[], int studentGrade[]) {
boolean flag = true;
while (flag) {
flag = false;
for (int j = 0; j < studentNames.length - 1; j++) {
for (int i = j + 1; i < studentNames.length; i++) {
if (studentNames[i].compareTo(studentNames[j]) < 0) {
String temp = studentNames[j];
studentNames[j] = studentNames[i];
studentNames[i] = temp;
// Here i want to place another array that sorts the grade?? how do i do that?
}
}
System.out.println(Arrays.toString(studentNames));
System.out.println(Arrays.toString(studentGrade));
}
}
}
}
Upvotes: 2
Views: 1787
Reputation: 34618
In this particular case, the solution is relatively easy. In this place, where you exchange the two student names:
for (int i = j + 1; i < studentNames.length; i++) {
if (studentNames[i].compareTo(studentNames[j]) < 0) {
String temp = studentNames[j];
studentNames[j] = studentNames[i];
studentNames[i] = temp;
}
}
You also exchange the corresponding grades at the same time:
for (int i = j + 1; i < studentNames.length; i++) {
if (studentNames[i].compareTo(studentNames[j]) < 0) {
String temp = studentNames[j];
studentNames[j] = studentNames[i];
studentNames[i] = temp;
int tempGrade = studentGrades[j];
studentGrades[j] = studentGrades[i];
studentGrades[i] = tempGrade;
}
}
So, whenever you do a switch of two student names, you switch the corresponding grades at the same time. This will keep the two arrays synchronized.
But as everybody else has been recommending, the better way is to create a class that represents a student - both name and grade. Why? Because in a real world case, a student may have other data, such as different subjects and their matching grades, an attendance record, contact information, whatever the university needs.
And having to add that to the loop for each such data item will make it intractable. If you have all the information in one record, you can just exchange record references, and then the whole data is exchanged together.
The basis for this is a class like:
class Student implements Comparable<Student> {
private String name;
private int grade = 0;
public Student( String name ) {
this.name = name;
}
public void setGrade( int grade ) {
this.grade = grade;
}
// In addition, you'll have getName(), getGrade(),
// and possibly a good `toString()` for printing a
// student record.
@Override
public int compareTo( Student otherStudent ) {
return this.name.compareTo( otherStudent.name );
}
}
Now you can define an array such as:
Student[] students = new Students[numbers];
And you can sort it directly with Arrays.sort()
because Student
implements Comparable
, or you can do your own sorting algorithm and use the compareTo
method. Your loop would be:
for (int i = j + 1; i < students.length; i++) {
if (students[i].compareTo(students[j]) < 0) {
Student temp = students[j];
students[j] = students[i];
students[i] = temp;
}
}
Upvotes: 1
Reputation: 2043
You should really have an abstraction representing a Student, e.g.
public class Student {
Integer grade;
String name;
// getters and setters omitted
}
Then, you'll face the problem of extending the Comparator interface multiple times with different types (Integer and String). At this point, read this :
Using Comparable for multiple dynamic fields of VO in java
Upvotes: 0
Reputation: 2085
Your problem is that when you sort one array (say your student name list), your second array cant keep up with the same way.... apples and oranges.
You have somes solutions. The one that comes in mind right now is to use a map linking each name to its grade. You could also, well, use POO and declare a Studen object, that actually would look like a nicer solution, i'll let you read on Veselin's answer for that.
Let's look at the quickfix though, since i think that's why you're looking for :
Personally one workaround to your kinda-broken code would be to change your swap function to this :
if (studentNames[i].compareTo(studentNames[j]) < 0) {
String tmp = studentNames[j];
studentNames[j] = studentNames[i];
studentNames[i] = tmp;
int tmpGrade = studentGrade[i];
studentGrade[j] = studentGrade[i];
studentGrade[i] = tmpGrade;
}
But, i strongly recommend using either classes or a map.
Upvotes: 0
Reputation: 692
What you want to do, is Sort the grade array according to the student array i think, so in you for loop, everytime you switch a student, you want to switch the grade
for (int j = 0; j < studentNames.length - 1; j++) {
for (int i = j + 1; i < studentNames.length; i++) {
if (studentNames[i].compareTo(studentNames[j]) < 0) {
String temp = studentNames[j];
studentNames[j] = studentNames[i];
studentNames[i] = temp;
// Here i want to place another array that sorts the grade?? how do i do that?
int tempGrade = studentGrades[j];
studentGrades[j] = studentGrades[i]
studentGrades[i] = temp
}
}
System.out.println(Arrays.toString(studentNames));
System.out.println(Arrays.toString(studentGrade));
}
this design isn't that good, maybe take the advice from @Veselin Davidov in account
Upvotes: 0
Reputation: 310993
As noted above, the "correct" solution is probably to create a Student
object and have it contain the student's name and grade. However, if you really need to have two separate arrays, you could just perform the same swapping on on the grade array that you do on the name array:
if (studentNames[i].compareTo(studentNames[j]) < 0) {
String temp = studentNames[j];
studentNames[j] = studentNames[i];
studentNames[i] = temp;
int tempGrade = studentGrade[i];
studentGrade[j] = studentGrade[i];
studentGrade[i] = tempGrade;
}
Upvotes: 1
Reputation: 7071
The problem with your approach is that there is no relation between a student name and grade. If you sort the names and sort the grades you will end up with students with letter A having the least grades.
If that's a java assignment the best way to do it would be to create a data structure (class) called Student that has name and grade.
class Student{
String name;
int grade;
}
Then you will not have two arrays one with names and other with grades but just one array of Students and you will be able to sort that array by grades,names etc.
If you want a quicker solution that would be to use a map like Map<String,Integer>
that will contain the grade for each student.
If you want to use multiple array you can make the sortAlgorithm
method to swap the same indexes in both arrays (not only in the names array) and this way you will end up with grades sorted by names. This is the worst approach IMO because you depend too much on the array indexes instead of having some relation between the objects.
Upvotes: 5