HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Sorting algorithm

Submitted by: @import:stackexchange-codereview··
0
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.

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 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 the LeistungComparer.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.