2

In my app I want to show football tables from different leagues for example the English Premier League and the Spanish Primera Division.

I created a SeasonTableTeamObject where I save all values. (TeamID, points, goals, conceded goals, playedGames, wins, draws, defeats)

public class SeasonTableTeamObject
{
    public int Points;
    public int Goals;
    public int AgainstGoals;
    public int TeamID;
    public string Teamname;
    public int PlayedGames;
    public int WinGames;
    public int DrawGames;
    public int LostGames;
    public int Rank;
    public int GoalDifference => (Goals - AgainstGoals);


    public SeasonTableTeamObject(int points, int goals, int againstGoals, int team, string teamName)
    {
        Points = points;
        Goals = goals;
        AgainstGoals = againstGoals;
        TeamID = team;
        Teamname = teamName;
        PlayedGames = 0;
        WinGames = 0;
        DrawGames = 0;
        LostGames = 0;
    }
}

Then I created a list with these SeasonTableTeamObjects for each league. (Each club in this league has its own SeasonTableTeamObject)

Now comes the tricky part: these leagues have different rules. I created a variable inside the league class to distinguish between the rule sets.

public class League
{
    public List<Match> ListOfAlreadyPlayedMatches;
    public List<SeasonTableTeamObject> SeasonTableList;
    public int Rules;
}

public class Match 
{
    public int HomeTeamId;
    public int AwayTeamId;
    public int WinnerTeamId;
}

In the Premier League you sort the table like this:

  1. Points
  2. Goal difference
  3. Goals

    SeasonTableList.OrderByDescending(p => p.Points).ThenByDescending(p => p.GoalDifference).ThenByDescending(p => p.Goals).ToList();

In the Spanish Primera Division:

  1. Points
  2. Direct comparison (without away goals rule)
  3. Goal difference

Direct comparison means the result of the matches between the clubs that have the same amount of points. For example Real Madrid and Barcelona have both 20 Points. Then you have to compare the matches between these two clubs. (I created a WinnderTeamId in Match to do this. I assume that there must be a winner in each game for simplification).

Questions: It was no problem to sort the list by points, goals etc, but how can I achieve the behavior of the spanish league. (I have a list of matches where I can find the specific games, but I have no idea how to do this. I read something about the IComparable and the IComparer but I don't know if this is the correct way to reach my goals...)

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
basti12354
  • 2,490
  • 4
  • 24
  • 43
  • 1
    What do you mean by: 2. Direct comparison – Merhat Pandzharov Jan 30 '19 at 08:56
  • Oh sorry (football vocabulary ;)) --> Direct comparision means the result of the matches between the clubs that have the same amount of points. For example Real Madrid and Barcelona have both 20 Points. Then you have to compare the matches between these two clubs. (I created a WinnderTeamId in Match to do this) – basti12354 Jan 30 '19 at 08:58

2 Answers2

2

In order to implement a more complex comparison method, you can use either IComparable<T> or IComparer<T>. As you want to implement different ways to compare the objects, you'd create several classes that implement IComparer<SeasonTableTeamObject> (one for the Premier League comparison and another one for the Primera Division).

This interface defines a method called Compare that takes two objects and compares them using the code in the method. As a result, it returns

  • -1 if x is less than y
  • 0 if x and y are equal (in terms of the comparison)
  • 1 if x is greater than y

When sorting the objects, you can use the comparer in the OrderBy to create the sort order you like, e.g.:

myItems.OrderBy(x => x, new MyComparer());

If you want to compare Premier League results, you'd use the comparer for the Premier League, otherwise the comparer for the Primera Division.

Markus
  • 20,838
  • 4
  • 31
  • 55
  • Thanks! Just for clarification: If I do this I could call "SeasonTableList.OrderByDescending(p => p.Points).ThenBy(x => x, new MyComparer()).ToList(); " ? What do you mean with "several objects"? Does that mean that I should create several league objects and define an individual Compare for each of them? – basti12354 Jan 30 '19 at 09:18
  • I'd suggest to create a comparer for the Premier League and another one for the Primera division. The comparer contains the complete set of rules for the respective league. You would only have a single `OrderBy` instead of multiple `OrderBy` and `ThenBy`s. In addition, you could create comparers for the single steps of the comparison, e.g. `PointsComparer`, `DirectComparisonComparer` so that you can assemble the league comparers from the single steps. – Markus Jan 30 '19 at 09:20
1

Your comparer could look like this:

(I have not tried to understand the rules for comparison, you have to fill out the logic)

public class SpanishSeasonTableTeamObjectComparer : IComparer<SeasonTableTeamObject>
{
    public Compare(SeasonTableTeamObject x, SeasonTableTeamObject y)
    {
         if(x.Points != y.Points)
         {
             return x.Points.CompareTo(y.Points);
         }

         // stack your various comparisons here, pattern like above...

         // if everything above is equal, compare on goals
         return x.Goals.CompareTo(y.Goals);
    }
}

It seems appropriate to have separate comparer classes for each league. Then you will do your sort with one call, like SeasonTableList.OrderByDescending(new SpanishSeasonTableTeamObjectComparer()) It seems also like a good idea to create unit tests for the comparer to validate that it sorts correctly. Please note that this kind of comparison will not be possible to run against the database objects IQueryable<SeasonTableTeamObject>. It needs to be run in memory.

mortb
  • 9,361
  • 3
  • 26
  • 44