Páginas

quinta-feira, 17 de março de 2011

Ordenando com auxílio de RegEx

Outro dia o Gustavo Bergamim perguntou ao Fabrício Doi e eu como realizar a ordenação da seguinte lista utilizando Regular Expression.

  • 1.3.5 - TESTE
  • 1.3.42 - TESTE
  • 2.1.4 - TESTE
  • 1 - TESTE
  • 10.1 - TESTE
  • 1.1 - TESTE
  • 2.1 - TESTE
  • 20.3 - TESTE
  • 2.5 - TESTE
  • 1.3 - TESTE
  • XYZ
  • Abc
  • Comparer

Se você adicionar estes itens em uma lista genérica de string e tentar realizar uma ordenação simples utilizando o método Sort, o resultado sairá errado, por isso utilizamos RegEx para facilitar a ordenação.

Vamos ao trabalho!!

Colocamos os itens em uma lista genérica de string e utilizamos o método Sort, passando por parâmetro a instância de uma classe que implementa a interface IComparer<>.

Classe Program:
class Program
{
    static void Main(string[] args)
    {
        List lista = new List();
        lista.Add("1.3.5 - TESTE");
        lista.Add("1.3.42 - TESTE");
        lista.Add("1.3.42 - ABC");
        lista.Add("2.1.4 - TESTE");
        lista.Add("1 - TESTE");
        lista.Add("10.1 - TESTE");
        lista.Add("1.1 - TESTE");
        lista.Add("2.1 - TESTE");
        lista.Add("20.3 - TESTE");
        lista.Add("2.5 - TESTE");
        lista.Add("1.3 - TESTE");
        lista.Add("Comparer");
        lista.Add("XYZ");
        lista.Add("Abc");

        lista.Sort(new numeracaoComparer());

        lista.ForEach(p => Console.WriteLine(p));

        Console.ReadKey();
    }
}

Nesta classe abaixo (numeracaoComparer), que implementa a interface IComparer utilizamos um RegEx para capturarmos as informações da numeração e assim poder ordenar pelos números contidos da numeração.

public class numeracaoComparer : IComparer
{
    #region IComparer Members

    public int Compare(string x, string y)
    {
        Regex rg = new Regex(@"((\d+)((\.(\d+))*)*)*(.*?)");

        Match mX = rg.Match(x);
        Match mY = rg.Match(y);

        int a = 0;
        int b = 0;

        if (int.TryParse(mX.Groups[2].Value, out a) && int.TryParse(mY.Groups[2].Value, out b))
        {
            int retorno = a.CompareTo(b);
            if (retorno == 0)
            {
                CaptureCollection cX = mX.Groups[5].Captures;
                CaptureCollection cY = mY.Groups[5].Captures;

                int qtdPontos = Math.Min(cX.Count, cY.Count);

                int c = 0;
                for (int i = 0; i < qtdPontos; i++)
                {
                    c = Convert.ToInt32(cX[i].Value).CompareTo(Convert.ToInt32(cY[i].Value));
                    if (c != 0)
                        return c;
                }

                if ((cX.Count - cY.Count) != 0)
                    return (cX.Count - cY.Count);
                else
                    return string.Compare(x, y);
            }
            return retorno;
        }
        else
        {
            return string.Compare(x, y);
        }
    }

    #endregion
}
Resultado da execução da classe Program:

0 comentários:

Postar um comentário