Guide C# – Ordinamento personalizzato degli ArrayList in C#

help-thumbQuesto è uno di quei problemi che nascono quando si comincia a lavorare con moli di dati decisamente elevati e per i quali occorre magari un modo per ordinarli senza dover operare con algoritmi di sort vari tra tutti quelli disponibili e tanto cari agli amici matematici che si occupano di informatica. Il framework infatti, ci mette a disposizione un metodo automatizzato per ordinare automaticamente un qualsiasi tipo di collezione di dati non FIFO (quindi ArrayList, List ecc.).

Questo metodo consiste nell’utilizzare il metodo Sort che appartiene appunto a queste serie di dati:

ArrayList lista = new ArrayList();
lista.Add("C");
lista.Add("B");
lista.Add("A");
lista.Sort();

Quello che otteniamo è così una lista ordinata in ordine alfabetico, quindi avremo prima l’elemento “A”, poi “B” ed infine “C”.

NB: E’ possibile ordinare in senso inverso tramite l’utilizzo di 2 metodi separatamente. Per primo il metodo Sort che ordina in un verso e poi tramite il metodo Reverse che ordina la collezione di dati in senso inverso all’attuale. [1]

Quello che però più spesso accade è voler decidere noi il metodo di ordinamento. Supponiamo ad esempio di avere la necessità di ordinare le lettere A, B e C secondo questo ordine:

  1. B > C
  2. C > A

che implicitamente significa che B > C. Quindi vogliamo avere come ordine finale “B”, “C” e “A”. Ovviamente tramite i metodi standard questo non è possibile, ecco perciò che vediamo come fare grazie all’interfaccia IComparer.

Il metodo Sort infatti, prevede un argomento di tipo IComparer, ovvero un oggetto che mette a disposizione un metodo Compare che prevede come argomenti due valori di tipo object e che ragiona secondo la seguente logica:

  • Se x < y allora ritorno -1
  • Se x > y allora ritorno 1
  • Se x = y allora ritorno 0

Creo così una classe MyStringComparer che estende l’interfaccia e quindi il suddetto metodo ed al cui interno occorre mettere il codice per fare in modo di ordinare i valori nel modo che vogliamo noi secondo la logica appena descritta:

public class MyStringComparer : IComparer
{
#region IComparer Members

public int Compare(object objx, object objy)
{
//se sono uguali non ho problemi e ritorno 0
if (objx.Equals(objy))
return 0;

switch (objx.ToString())
{
//se il primo valore è B, allora è sempre minore degli altri
case "B":
return -1;
//se è C devo controllare
case "C":
//perchè se è A allora va prima altrimenti dopo
if (objy.ToString() == "A")
return -1;
else
return 1;
//se è A invece va sempre dopo gli altri
case "A":
return 1;
}
return 0;
}

#endregion
}

A questo punto, proviamo questo codice:

static void Main(string[] args)
{
ArrayList lista = new ArrayList();

lista.Add("C");
lista.Add("B");
lista.Add("A");
lista.Add("C");
lista.Add("B");
lista.Add("A");

lista.Sort(new MyStringComparer());

foreach (string str in lista)
{
Console.WriteLine(str);
}

Console.Read();
}

Ovviamente, ciò che otteniamo è la serie: BBCCAA, esattamente come volevamo ok emoticon

Ora che siamo giunti a questa conclusione, ci viene però in mente che potremmo trovare un modo per migliorare l’ordinamento inverso della lista, visto che prima usavamo 2 metodi per farlo… invece è possibile grazie ad 1 solo. Creiamo un comparatore inverso! [2]

public class ReverseOrder : IComparer
{
#region IComparer Members

public int Compare(object objx, object objy)
{
return String.Compare((string)objx, (string)objy) * -1;
}

#endregion
}

Ecco fatto. Relativamente semplice, ma soprattutto molto ordinato (scusate il gioco di parole asd emoticon asd emoticon )

Alla prossima! ok emoticon

This entry was posted in Linguaggi .Net, Programmazione and tagged , , , , , , , , . Bookmark the permalink.

Lascia un Commento

L'indirizzo email non verrà pubblicato. I campi obbligatori sono contrassegnati *

*

È possibile utilizzare questi tag ed attributi XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>