1

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.

fkr
  • 155
  • 3
  • 9
  • 21

5 Answers5

1

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

  • If the same, check next character
  • If greater, swap, were done here.
  • If less, do nothing, were done here.

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));
        }
    }
James
  • 9,774
  • 5
  • 34
  • 58
  • where i am suppose to add this. before or after the **if**? – fkr Jan 24 '14 at 11:24
  • @fkr Instead of, it replaces the if – James Jan 24 '14 at 11:31
  • you also need the change to the for loop, I'll edit my answer to be clearer – James Jan 24 '14 at 11:34
  • ok it works now, BUT it sorts in opposite alphabetical way (etc....Smoke, Poke, Hoke, instead of ...Hoke, Poke, Smoke – fkr Jan 24 '14 at 11:40
  • @fkr Either change > to < or swap c1 and c2 – James Jan 24 '14 at 11:49
  • i did try that before i replied here and nothing has changed. blows my mind. Either > or < ,sorts the same. Yeah it does blow my mind – fkr Jan 24 '14 at 11:54
  • @fkr Sorry can't help you there, I've run the algorithm on my machine and it works as expected. There must be another mistake in your code. – James Jan 24 '14 at 12:05
  • Well thank you for your time and everything..ill try to figure sth out. Ill mark your answer is the right one:) – fkr Jan 24 '14 at 12:10
  • one more question...if you look at my original post...must there something be changed with **for** at the bottom, after the console.writeline? – fkr Jan 24 '14 at 12:15
  • @fkr I've added the complete method I used. – James Jan 24 '14 at 12:21
1

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]) ) )
Moho
  • 15,457
  • 1
  • 30
  • 31
0
using System.Linq;

Student[] sorted = studentList.OrderBy(x=>x.lastName).ThenBy(x=>x.name).ToArray();
vchyzhevskyi
  • 753
  • 1
  • 11
  • 20
0

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 
Marco
  • 22,856
  • 9
  • 75
  • 124
0

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:

Results.

RePierre
  • 9,358
  • 2
  • 20
  • 37
  • thank you very much but this is supposed to be not a complex program, which means i cannot use either Icomparer or CompareTo. Subject rules, not mine =\ – fkr Jan 24 '14 at 11:16