Reputation: 155
This is another homework here. I need to sort students by it's last name and first name (firstly last name and secondly first name). The full list of students must be edited alphabetical.
What works so far:
If i type in 3 students with same Last name, it sorts correctly.
Lets say:
Richardson Mark Richardson Mike Richardson Matt
The correct sorting order is:
Richardson Mark Richardson Matt Richardson Mike
It also work when last name's start with same letter and are look alike
Lets say:
Richardson Mark Richmond Luke Rikkard Matt
Sorts as:
Richardson Mark Richmond Luke Rikkard Matt
My problem
The code doesn't sort 3 entirely different last name's (etc, Richardson, Markson, Bekhs)...
Please notice that only basic functions are allowed and must be programmed like bellow!
private static void sortAlpphabetical(Student[] studentList)
{
for (int i = 1; i < studentList.Length; i++)
{
for (int j = 0; j < studentList.Length - 1; j++)
{
string lastName1 = studentList[j].lastName.ToLower() + studentList[j].name.ToLower();
string lastName2 = studentList[j + 1].lastName.ToLower() + studentList[j + 1].name.ToLower();
for (int k = 0; k < lastName1.Length; k++)
{
if (returnIndex(lastName2[k]) > returnIndex(lastName1[k]))
{
Student currentStudent = studentList[j];
studentList[j] = studentList[j + 1];
studentList[j + 1] = currentStudent;
}
}
}
}
Console.WriteLine("List of students:\n");
for (int i = 0; i < studentList.Length; i++)
{
Console.WriteLine("//code");
}
}
When i try to sort 3 different last names, it gives me Index was outside the bounds of the array. Error
An unhandled exception of type 'System.IndexOutOfRangeException' occurred in work.exe
Additional information: Index was outside the bounds of the array.
Upvotes: 1
Views: 7469
Reputation: 770
using System.Linq;
Student[] sorted = studentList.OrderBy(x=>x.lastName).ThenBy(x=>x.name).ToArray();
Upvotes: 0
Reputation: 9985
k here makes the assumption that lastName1 is longer than lastName2
for (int k = 0; k < lastName1.Length; k++)
{
if (returnIndex(lastName2[k]) > returnIndex(lastName1[k]))
{
Student currentStudent = studentList[j];
studentList[j] = studentList[j + 1];
studentList[j + 1] = currentStudent;
}
}
This should prevent that by preventing the loop checking beyond the length of which ever is shorter
int shortestNameLength = Math.Min(lastName1.Length, lastName2.Length);
for (int k = 0; k < shortestNameLength ; k++)
After some testing your algorithm has another problem. It will continue comparing to the last character in the name. It needs to stop once it has determined the order
Compare a character
To summarise, replace
for (int k = 0; k < lastName1.Length; k++)
{
if (returnIndex(lastName2[k]) > returnIndex(lastName1[k]))
{
Student currentStudent = studentList[j];
studentList[j] = studentList[j + 1];
studentList[j + 1] = currentStudent;
}
}
with
int shortestNameLength = Math.Min(lastName1.Length, lastName2.Length);
for (int k = 0; k < shortestNameLength ; k++)
{
int c1 = returnIndex(lastName1[k]);
int c2 = returnIndex(lastName2[k]);
if (c1 == c2)
{
continue;
}
if (c1 > c2)
{
Student currentStudent = studentList[j];
studentList[j] = studentList[j + 1];
studentList[j + 1] = currentStudent;
}
break;
}
The complete method now looks something like this...
private static void sortAlpphabetical(Student[] studentList)
{
for (int i = 1; i < studentList.Length; i++)
{
for (int j = 0; j < studentList.Length - 1; j++)
{
string lastName1 = studentList[j].lastName.ToLower() + studentList[j].name.ToLower();
string lastName2 = studentList[j + 1].lastName.ToLower() + studentList[j + 1].name.ToLower();
int shortestNameLength = Math.Min(lastName1.Length, lastName2.Length);
for (int k = 0; k < shortestNameLength; k++)
{
int c1 = returnIndex(lastName1[k]);
int c2 = returnIndex(lastName2[k]);
if (c1 == c2)
{
continue;
}
if (c1 > c2)
{
Student currentStudent = studentList[j];
studentList[j] = studentList[j + 1];
studentList[j + 1] = currentStudent;
}
break;
}
}
}
Console.WriteLine("List of students:\n");
for (int i = 0; i < studentList.Length; i++)
{
Console.WriteLine(string.Format("{0} {1}", studentList[i].name, studentList[i].lastName));
}
}
Upvotes: 1
Reputation: 9566
You can use IComparer interface to specify the order of your objects.
This is the code I scrapped in LinqPad (using the names provided by @Serv - yeah I am that lazy...)
void Main()
{
var students = new List<Student>()
{
new Student("Alphonso", "Zander"),
new Student("Berta", "Zander"),
new Student("Giacomo", "Zander"),
new Student("Marc", "Lastly"),
new Student("God", "Allmighty")
};
students.Sort(new StudentComparer());
students.Dump();
}
class Student
{
public Student(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
public string FirstName{get;set;}
public string LastName{get;set;}
}
class StudentComparer:IComparer<Student>
{
public int Compare(Student a, Student b)
{
var lastName = a.LastName.CompareTo(b.LastName);
if(lastName == 0)
return a.FirstName.CompareTo(b.FirstName);
return lastName;
}
}
Unless you want to rewrite the sorting algorithm used by Sort
method the code above should suffice for you.
And here are the results:
Upvotes: 0
Reputation: 16498
You need to check the length of the arrays you're accessing. If lastName1
doesn't have a character at offset k
(i.e. lastName1.length == k
), we know lastName2
is greater than lastName1
. If lastName2
does not have a character at offset k
(i.e. lastName2.length <= k
), it can't be greater than lastName1
.
Change
if (returnIndex(lastName2[k]) > returnIndex(lastName1[k]))
to
if( lastName1.length == k ||
( lastName2.length > k &&
returnIndex(lastName2[k]) > returnIndex(lastName1[k]) ) )
Upvotes: 1
Reputation: 23937
Just scratched this up in LinqPad, which should give you the desired output, unless you are supposed to use for-loops and classic arrays.
void Main()
{
var students = new List<student>()
{
new student("Alphonso", "Zander"),
new student("Berta", "Zander"),
new student("Giacomo", "Zander"),
new student("Marc", "Lastly"),
new student("God", "Allmighty")
};
var sortedStudents = students.OrderBy(s => s.lastName).ThenBy(s => s.firstName).Dump();
}
// Define other methods and classes here
class student
{
public student(string fname, string lname)
{
this.firstName = fname; this.lastName = lname;
}
public string firstName { get; set; }
public string lastName { get; set; }
}
Output:
firstName lastName
God Allmighty
Marc Lastly
Alphonso Zander
Berta Zander
Giacomo Zander
Upvotes: 0