Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

List sort challenge

Status
Not open for further replies.

RickBeddoe

Programmer
Nov 18, 2008
32
0
0
US
Hello folks,

I am having a dilemma with the list.sort method.

The data I'm using is stored in the 'heading' member of the 'Contexts' objects (p1,p2). Here's my data:

3 months ending 9/30/2007
3 months ending 9/30/2008
9 months ending 9/30/2007
9 months ending 9/30/2008

Here is my sort code:

lst.Sort(delegate(Contexts p1, Contexts p2)

{

return p1.heading.CompareTo(p2.heading);

}

);

Using lst.Sort as you see above, yields the result you expect above. What I'd really like to do is a sort within a sort. I would like my data to look like this (note the years are descending within each month period):

3 months ending 9/30/2008
3 months ending 9/30/2007
9 months ending 9/30/2008
9 months ending 9/30/2007

I tried to put another anonymous method within the sort method, but that did not do what I wanted (it threw an exception).

Any help will be appreciated.

Cheers,

Rick
 
if this is just text, then you will need to parse the text and then create a combined sort.

I would recommend breaking this into parts. instead of doing this all at once.
1. get the data, not the text. this would be the number of months and the date.
2. sort by months asc, then by date desc.
3. then create a list of text
4. then send the array of text to the gui
Code:
class Dto
{
   public int number {get;set;}
   public DateTime date {get;set;}
}

public class AggregatedSort<T> : IComparer<T>
{
   public AggregatedSort(IComparer<T> first, IComparer<T> second)
   {
       this.first = first;
       this.second = second;
   }

   public int Compare(T x, T y)
   {
       var result = first.Compare(x, y);
       if(result == 0) return second.Compare(x, y);
       return result;
   }
}

public class Reverse<T> : IComparer<T>
{
   public Reverse(IComparer<T> original)
   {
       this.original = original;
   }

   public int Compare(T x, T y)
   {
       return original.Compare(x, y) * -1;
   }
}
now that we have these generic sorts we can combine them to sort the dto class.
Code:
var dtos = get_dtos();
var by_number = (x,y) => x.number.Compare(y.number);
var by_date = (x,y) => x.date.Compare(y.date);
var by_date_descending = new Reverse<Dto>(by_date);
var aggregate_sort = new AggregateSort<Dto>(by_number, by_date_descending);

dtos.Sort(aggregate_sort);
now we just convert the text and return
Code:
var texts = dtos.ConvertAll(x=>string.Format("{0} months ending {1:MM/dd/yyyy}", x.number, x.date));
return texts;

if you only have access to the text string then i would parse the text into number/date objects and then proceed with the steps above.

note: there is alot of room to refactor how to create sorts. for example, use extension methods we could do this
Code:
public static class ComparerExtensions
{
   public static IComparer<T> reverse(this IComparer<T> orginal)
   {
      return new Reverse<T>(original);
   }


   public static IComparer<T> then_by(this IComparer<T> first, IComparer<T> second)
   {
      return new AggregateSort<T>(first, second);
   }
}[code]
now we can do this
[code]
var descending new Ascending<Dot>(...).reverse();
or
var both = new First<Dto>(...).then_by(new Second<Dto>());
we could also refactor the creation of sorts to
Code:
Order<Dto>.by(x=>x.number).then_by(x=>x.date).reverse();
but that's beyond the scope of this post:)

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
Thanks Jason. I may give this a try. I had some help figuring another method using regex. If I can get that to work the way I need it to, I'll post here.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top