IComparer

Noen gang lurt på hvordan man ordner støtte for å sortere objekter på flere forskjellige måter. F.eks. slik mange nettbutikker gjør, hvor de tilbyr deg sortering på pris, mest aktuelt, popularitet, o.s.v.?


Dette er enkelt å ordne f.eks. med grensesnittet IComparer. Men først trenger vi en eksempelklasse som senere skal gi de objektene vi ønsker å sortere:

public class Vare
{
   public string Navn { get { return navn; } }
   private string navn;

   public string Produsent { get { return produsent; } }
   private string produsent;

   public int Pris { get { return pris; } }
   private int pris;

   public DateTime Lanseringsdato { get { return lanseringsdato; } }
   private DateTime lanseringsdato;

   public Vare(string navn, string produsent, int pris, DateTime lanseringsdato)
   {
      this.navn = navn;
      this.produsent = produsent;
      this.pris = pris;
      this.lanseringsdato = lanseringsdato;
   }

   public override string ToString()
   {
      string info = "";
      info += "----------------------------------------------------------------------\n";
      info += "Navn: " + navn + "\n";
      info += "Produsent: " + produsent + "\n";
      if (lanseringsdato != DateTime.MinValue)
      {
         info += "Lansert en gang etter: " + lanseringsdato.Day + "." + lanseringsdato.Month + "." + lanseringsdato.Year + "\n";
      }
      info += "Selges for " + pris + " NOK\n";
      info += "----------------------------------------------------------------------";
      return info;
   }

   public static IComparer SorterBrukPriser { get { return new VareSortering.Prisen(); } }
   public static IComparer SorterBrukProdusent { get { return new VareSortering.Produsent(); } }
   public static IComparer SorterBrukLanseringsdato { get { return new VareSortering.Lanseringsdato(); } }
}

Her er det egentlig ikke så mye som er interessant, bortsett fra de tre siste linjene som man refererer til når man vil bruke de forskjellige sorteringsmåtene.

Disse implementeres i det som blir en hjelpeklasse til klassen Vare over:

public class VareSortering
{
   public class Prisen : IComparer
   {
      public int Compare(object objekt1, object objekt2)
      {
         Vare vare1 = objekt1 as Vare;
         Vare vare2 = objekt2 as Vare;

         if (vare1 != null && vare2 != null)
         {
            if (vare1.Pris < vare2.Pris)
            {
               return -1;
            }
            else if (vare1.Pris > vare2.Pris)
            {
               return 1;
            }
            else
            {
               return 0;
            }
         }
         else
         {
            throw new ArgumentException("Begge objekt som skal sammenlignes må være varer!");
         }
      }
   }

   public class Produsent : IComparer
   {
      public int Compare(object objekt1, object objekt2)
      {
         Vare vare1 = objekt1 as Vare;
         Vare vare2 = objekt2 as Vare;

         if (vare1 != null && vare2 != null)
         {
            if (vare1.Produsent.CompareTo(vare2.Produsent) < 0)
            {
               return -1;
            }
            else if (vare1.Produsent.CompareTo(vare2.Produsent) > 0)
            {
               return 1;
            }
            else
            {
               return 0;
            }
         }
         else
         {
            throw new ArgumentException("Begge objekt som skal sammenlignes må være varer!");
         }
      }
   }

   public class Lanseringsdato : IComparer
   {
      public int Compare(object objekt1, object objekt2)
      {
         Vare vare1 = objekt1 as Vare;
         Vare vare2 = objekt2 as Vare;

         if (vare1 != null && vare2 != null)
         {
            if (vare1.lanseringsdato.Year < vare2.lanseringsdato.Year)
            {
               return -1;
            }
            else if (vare1.lanseringsdato.Year > vare2.lanseringsdato.Year)
            {
               return 1;
            }
            else
            {
               if (vare1.lanseringsdato.Month < vare2.lanseringsdato.Month)
               {
                  return -1;
               }
               else if (vare1.lanseringsdato.Month > vare2.lanseringsdato.Month)
               {
                  return 1;
               }
               else
               {
                  if (vare1.lanseringsdato.Day < vare2.lanseringsdato.Day)
                  {
                     return -1;
                  }
                  else if (vare1.lanseringsdato.Day > vare2.lanseringsdato.Day)
                  {
                     return 1;
                  }
                  else
                  {
                     return 0;
                  }
               }
            }
         }
         else
         {
            throw new ArgumentException("Begge objekt som skal sammenlignes må være varer!");
         }
      }
   }
}

Her er VareSortering gjort til en egen klasse utenfor Vare, men den kunne også vært opprettet inni og gjort privat da omverdenen ikke trenger direkte tilgang.

Og endelig for å teste om dette henger sammen og fungerer kan vi kjøre følgende:

class Program
{
   static void Main(string[] args)
   {
      Vare[] varer = new Vare[5];
      varer[0] = new Vare("Intel Pentium G4400 3.3GHz Socket 1151 Box", "Intel", 533, new DateTime(2015, 8, 1));
      varer[1] = new Vare("Corsair Vengeance LPX Black DDR4 PC19200/2400MHz CL14", "Corsair", 399, new DateTime(2015, 1, 1));
      varer[2] = new Vare("ASUS Prime B250M-C", "ASUS", 858, new DateTime(2015, 1, 1));
      varer[3] = new Vare("Fractal Design Core 1100 (Sort)", "Fractal Design", 379, DateTime.MinValue);
      varer[4] = new Vare("Corsair VS450 V2 450W", "Corsair", 419, new DateTime(2015, 1, 1));

      // Før sortering
      Console.WriteLine("Før sortering:");
      foreach (Vare vare in varer) Console.WriteLine(vare);
      Console.WriteLine();

      // Etter prissortering
      Console.WriteLine("Etter prissortering:");
      Array.Sort(varer, Vare.SorterBrukPriser);
      foreach (Vare vare in varer) Console.WriteLine(vare);
      Console.WriteLine();

      // Etter produsentsortering
      Console.WriteLine("Etter produsentsortering:");
      Array.Sort(varer, Vare.SorterBrukProdusent);
      foreach (Vare vare in varer) Console.WriteLine(vare);
      Console.WriteLine();

      // Etter lanseringsdato
      Console.WriteLine("Etter lanseringsdatosortering:");
      Array.Sort(varer, Vare.SorterBrukLanseringsdato);
      foreach (Vare vare in varer) Console.WriteLine(vare);
      Console.WriteLine();

      Console.ReadLine();
   }
}

.. som da resulterer i:

Altså virker alle de tre forskjellige sorteringsmåtene, og har man flere man ønsker å legge inn er dette ikke noe problem.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert.