سؤال

I am trying to modify this code that already exists.The code was developed around 2008 and I am trying to fix the sort issue. I am also thinking of changing the code but wanted to fix the issue first.

ArrayList lineEmpNrs = new ArrayList();
taMibMsftEmpDetails employeeDetails; //taMibMsftEmpDetails is a custom class file

while (!HeaderFile.EndOfStream) //headerfile is employee information text file.
{
    headerRow = HeaderFile.ReadLine();
    headerFields = headerRow.Split(',');
    employeeDetails = BuildLine(headerFields[1],headerFields[2],headerFields[3]);
    lineEmpNrs.Add(employeeDetails);
}

 private taMibMsftEmpDetails BuildLine(string EmpId, string EmpName, String ExpnsDate)
 {
     taMibMsftEmpDetails empSlNr = new taMibMsftEmpDetails();
     empSlNr.EmployeeId  = EmpId;
     empSlNr.EmployeeName   = EmpName;
     empSlNr.ExpenseDate = ExpnsDate;
     return empSlNr;
 }

The Headerfile contains employee expense details. The empID is the key here and the headerFile can contain 'n' number of lines with same EmpID appearing in random order in the file.

I use lineEmpNrs to build some other information based on EmpID. So I want to have lineEmpNrs sorted based on EmpID. I tried the regular sort method but it didn't work.

Please suggest.

هل كانت مفيدة؟

المحلول 2

This code is .Net 2.0 safe:

public static string ReadLines(StreamReader input)
{
    string line;
    while ( (line = input.ReadLine()) != null)
       yield return line;
}

private taMibMsftEmpDetails BuildLine(string EmpId, string EmpName, String ExpnsDate)
{
    taMibMsftEmpDetails empSlNr = new taMibMsftEmpDetails();
    empSlNr.EmployeeId  = EmpId;
    empSlNr.EmployeeName   = EmpName;
    empSlNr.ExpenseDate = ExpnsDate;
    return empSlNr;
}

List<taMibMsftEmpDetails> lineEmpNrs = new List<taMibMsftEmpDetails>();
foreach (string line in ReadLines(HeaderFile))
{
    headerFields = line.Split(',');
    lineEmpNrs.Add(BuildLine(headerFields[1],headerFields[2],headerFields[3]));
}
lineEmpNrs.Sort(delegate(taMibMsftEmpDetails a, taMibMsftEmpDetails a) 
   { 
      return a.EmployeeId.CompareTo(a.EmployeeId); 
   });    

If you can get to at least .Net 3.5 (still uses .Net 2.0 runtime), it gets that much simpler:

public static string ReadLines(StreamReader input)
{
    string line;
    while ( (line = input.ReadLine()) != null)
       yield return line;
}

var lineEmpNrs = ReadLines(HeaderFile)
   .Select(l => l.Split(','))
   .Select(l => new taMibMsftEmpDetails() 
       {
          EmployeeId   = l[1],
          EmployeeName = l[2],
          ExpenseDate  = l[3]
       })
   .OrderBy(l=> l.EmployeeId)
   .ToList();

نصائح أخرى

First - thus it is .Net 2.0 you can use strongly-typed generic list of type List<taMibMsftEmpDetails> instead of ArrayList:

List<taMibMsftEmpDetails> lineEmpNrs = new List<taMibMsftEmpDetails>();
// rest is same

Second - you can use method List<T>.Sort with Comparison<T> delegate to sort employees by id:

lineEmpNrs.Sort(delegate(taMibMsftEmpDetails e1, taMibMsftEmpDetails e2) { 
                   return e1.EmployeeId.CompareTo(e2.EmployeeId); 
                });

Instead of anonymous method you can create usual named method for comparing employees:

lineEmpNrs.Sort(CompareEmployees);

Also consider to improve naming in your code. Consider to use employees collection instead of lineEmpNrs, EmployeeDetails class instead of taMibMsftEmpDetails.

As pointed out below, this won't work on ArrayList, but you could convert lineEmpNrs to a List<taMibMsftEmpDetails>.

LINQ is perfect here.

var sortedList = lineEmpNrs.OrderBy(emp => emp.EmployeeId);

After seeing your comment, this will only work if you can bump your code from .NET 2.0 to 3.5 or higher.

You can use the ArrayList as a List

var enumerableCollection = from taMibMsftEmpDetails ln in lineEmpNrs
                                        orderby ln.EmployeeId
                                        select ln;

You can convert to Array or use the List

You can also load the data in to a DataTable and sort via a DataView.

    DataTable dt = new DataTable();
    dt.Columns.Add("EmpID");
    dt.Columns.Add("Field2");
    dt.Columns.Add("Field3");

    // Read file, split values, add to table
    while (!HeaderFile.EndOfStream) {

        headerRow  = HeaderFile.ReadLine();
        headerFields = headerRow.Split(',');

        // Create row and add it to the table
        DataRow dr = dt.NewRow();
        dr["EmpID"] = headerFields[0];
        dr["Field1"] = headerFields[1];
        dr["Field2"] = headerFields[2];
        dt.ImportRow(dr);
    }

    // Sort table by EmpID
    DataView dv = dt.DefaultView;
    dv.Sort = "EmpID ASC";
    dt = dv.ToTable();

The regular sort method should work alongside a custom compare method, something like the following:

private class sortByEmployeeIdHelper: IComparer
{
   int IComparer.Compare(object a, object b)
   {
       taMibMsftEmpDetails employeeA = (taMibMsftEmpDetails)a;
       taMibMsftEmpDetails employeeB = (taMibMsftEmpDetails)b;

       //employee id is numeric?
       int id = int.Parse(employeeA.EmployeeId);
       return id.CompareTo(int.Parse(employeeB.EmployeeId));
   }
}

IComparer myComparer = new sortByEmployeeIdHelper();
lineEmpNrs.Sort(myComparer);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top