patterncsharpMinor
Sorting algorithm
Viewed 0 times
sortingalgorithmstackoverflow
Problem
This is my ugly code which needs to sort my data. I'm not really familiar with C# since actually I'm a Java programmer.
How could this code be rewritten without loosing performance? I know I could use reflection, but it is bad for performance.
The classes:
The algorithm:
```
internal static IEnumerable Sort(List leistungen, IEnumerable sortings)
{
for (int i = 0; i string.Compare(a.Kunde,b.Kunde)*sort);
}
else
{
for (var j = 0; j string.Compare(a.Art, b.Art) * sort);
}
else if (sortings.ElementAt(i).Field.Equals("Angebot"))
{
leistungen[j].Leistungen.Sort((a, b) => string.Compare(a.Angebot, b.Angebot) * sort);
}
else if (sortings.ElementAt(i).Field.Equals("Jahr"))
{
leistungen[j].Leistungen.Sort((a, b) => string.Compare(a.Jahr, b.Jahr) * sort);
}
else if (sortings.ElementAt(i).Field.Equals("Berater"))
{
leistungen[j].Leistungen.Sort((a, b) => string.Compare(a.Berater, b.Berater) * sort);
}
How could this code be rewritten without loosing performance? I know I could use reflection, but it is bad for performance.
sortings is a list of the fields that have to be sorted and if it has to be ASC and DESC. leistungen is the data to be sorted.The classes:
public class Aufzeichnung
{
public string Mitarbeiter { get; set; }
public int Dauer { get; set; }
public double Kosten { get; set; }
}
public class Leistung
{
public int ID { get; set; }
public string Art { get; set; }
public string Angebot { get; set; }
public string Jahr { get; set; }
public string Berater { get; set; }
public string Assistent { get; set; }
public double Preis { get; set; }
public List Aufzeichnungen { get; set; }
}
public class LaufendeLeistung
{
public string Kunde { get; set; }
public List Leistungen { get; set; }
}The algorithm:
```
internal static IEnumerable Sort(List leistungen, IEnumerable sortings)
{
for (int i = 0; i string.Compare(a.Kunde,b.Kunde)*sort);
}
else
{
for (var j = 0; j string.Compare(a.Art, b.Art) * sort);
}
else if (sortings.ElementAt(i).Field.Equals("Angebot"))
{
leistungen[j].Leistungen.Sort((a, b) => string.Compare(a.Angebot, b.Angebot) * sort);
}
else if (sortings.ElementAt(i).Field.Equals("Jahr"))
{
leistungen[j].Leistungen.Sort((a, b) => string.Compare(a.Jahr, b.Jahr) * sort);
}
else if (sortings.ElementAt(i).Field.Equals("Berater"))
{
leistungen[j].Leistungen.Sort((a, b) => string.Compare(a.Berater, b.Berater) * sort);
}
Solution
Edit
My original answer does not address ascending / descending sorting dynamically. So here is my idea. Note that this is different from @ratchetFreak answer. The key is that an
The above in action:
Details
End Edit
NOTE: Original answer follows. It has not been modified.
The idomatic way to enable sorting is to implement the
then you can sort like this:
And if you want different sort algorithms then create an
IComparable Implementation
This demonstrates how to compare multiple properties. Both of your classes will implement using this pattern. When
My original answer does not address ascending / descending sorting dynamically. So here is my idea. Note that this is different from @ratchetFreak answer. The key is that an
IComparer automatically overrides an object's IComparable implementation.- New class,
LeistungComparer : Comparer
public abstract class Comparer : IComparer- so inherit and we get the interface.
- We'll pass a constructor parameter to tell which way to sort.
- Move
Leistung.CompareTo()code to this new class.
Leistung.CompareTo()will just call theLeistungComparer.Compare()- that's all!
The above in action:
// ***** default ascending sort
Leistung yourLeistung = new Leistung( );
Leistung yourLeistung2 = new Leistung( );
List yourList = new List();
yourList.Add(yourLeistung);
yourList.Add(yourLeistung2);
// stuff happens, then...
yourList.Sort();
// override
yourList.Sort( new LeistungComparer( SortOrder.descend ) );Details
public enum SortOrder { undefined, ascend, descend }
public class LeistungComparer : Comparer
{
protected int SortBy { get; set; }
///
/// Default sort order is ascending
///
/// defaults to ascend
public LeistungComparer( SortOrder sortOrder = SortOrder.ascend )
{
if ( sortOrder == SortOrder.ascend ) SortBy = 1;
if ( sortOrder == SortOrder.descend ) SortBy = -1;
if ( sortOrder == SortOrder.undefined )
throw new NotImplementedException( "Sort Order is undefined" );
}
public override int Compare( Leistung x, Leistung y )
{
int result = SortBy;
if ( x != null && y == null ) return result;
if ( x == null && y != null ) return result * SortBy;
if ( x == null && y == null ) return 0;
result = x.Art.CompareTo( y.Art ) * SortBy;
if ( result == 0 )
result = CompareAngebot( x, y );
return result * SortBy;
}
protected int CompareAngebot( Leistung x, Leistung y )
{
int result = SortBy;
result = x.Angebot.CompareTo( y.Angebot ) * SortBy;
if ( result == 0 )
result = CompareJahr( x, y );
return result;
}
protected int CompareJahr( Leistung x, Leistung y )
{
// you get the idea
return 1;
}
}
public class Leistung : IComparable
{
// properties removed for readability
protected LeistungComparer Comparer { get; set; }
public Leistung (LeistungComparer comparer = null){
Comparer = comparer ?? new LeistungComparer();
}
public int CompareTo( Leistung other )
{
return Comparer.Compare( this, other );
}
}End Edit
NOTE: Original answer follows. It has not been modified.
The idomatic way to enable sorting is to implement the
IComparable interface. And this will definitely simplify the sorting code. So:public class Leistungen : IComparable { }
public class Aufzeichnung : IComparable { }then you can sort like this:
List myLeistungen; // pretend we instantiated it too.
myLeistungen.Sort();And if you want different sort algorithms then create an
IComparer class for each one as suggested by @ratchetfreak. then you can do the following - which will override your IComparalble implementation in the class Leistungen:myLeistungen.Sort(myDifferentComparer);IComparable Implementation
This demonstrates how to compare multiple properties. Both of your classes will implement using this pattern. When
Leistungen.CompareTo() gets down to comparing its List, well Aufzeichnung.CompareTo() takes care of that!public class Leistungen : IComparable {
\\ implementing the generic version means we don't
\\ check for or cast to the correct type.
public int CompareTo(Leistungen other) {
int result = 1; // "this" is > "other"
if(other == null) return result;
result = this.Art.CompareTo(other.Art);
if(result == 0)
result = CompareAngebot(other);
return result;
}
protected int CompareAngebot(Leistungen other) {
int result = 1;
result = this.Angebot.CompareTo(other.Angebot);
if(result == 0)
result = CompareJahr(other);
return result;
}
protected int CompareJahr(Leistungen other) { // you get the idea }
// ....
protected int CompareAufzeichnungList(Leistungen other) {
// last property in our compare chain, so it's real simple
return this.Aufzeichnungen.CompareTo(other.Aufzeichnungen);
}
}Code Snippets
// ***** default ascending sort
Leistung yourLeistung = new Leistung( );
Leistung yourLeistung2 = new Leistung( );
List<Leistung> yourList = new List<Leistung>();
yourList.Add(yourLeistung);
yourList.Add(yourLeistung2);
// stuff happens, then...
yourList.Sort();
// override
yourList.Sort( new LeistungComparer( SortOrder.descend ) );public enum SortOrder { undefined, ascend, descend }
public class LeistungComparer : Comparer<Leistung>
{
protected int SortBy { get; set; }
/// <summary>
/// Default sort order is ascending
/// </summary>
/// <param name="sortOrder">defaults to ascend</param>
public LeistungComparer( SortOrder sortOrder = SortOrder.ascend )
{
if ( sortOrder == SortOrder.ascend ) SortBy = 1;
if ( sortOrder == SortOrder.descend ) SortBy = -1;
if ( sortOrder == SortOrder.undefined )
throw new NotImplementedException( "Sort Order is undefined" );
}
public override int Compare( Leistung x, Leistung y )
{
int result = SortBy;
if ( x != null && y == null ) return result;
if ( x == null && y != null ) return result * SortBy;
if ( x == null && y == null ) return 0;
result = x.Art.CompareTo( y.Art ) * SortBy;
if ( result == 0 )
result = CompareAngebot( x, y );
return result * SortBy;
}
protected int CompareAngebot( Leistung x, Leistung y )
{
int result = SortBy;
result = x.Angebot.CompareTo( y.Angebot ) * SortBy;
if ( result == 0 )
result = CompareJahr( x, y );
return result;
}
protected int CompareJahr( Leistung x, Leistung y )
{
// you get the idea
return 1;
}
}
public class Leistung : IComparable<Leistung>
{
// properties removed for readability
protected LeistungComparer Comparer { get; set; }
public Leistung (LeistungComparer comparer = null){
Comparer = comparer ?? new LeistungComparer();
}
public int CompareTo( Leistung other )
{
return Comparer.Compare( this, other );
}
}public class Leistungen : IComparable<Leistungen> { }
public class Aufzeichnung : IComparable<Aufzeichnung> { }List<Leistungen> myLeistungen; // pretend we instantiated it too.
myLeistungen.Sort();myLeistungen.Sort(myDifferentComparer);Context
StackExchange Code Review Q#104418, answer score: 6
Revisions (0)
No revisions yet.