2009-09-30 6 views
5

que tienen un requisito para ordenar algunas cadenas que contienen los datos de la siguiente manera:Cómo determinar de manera eficiente si una cadena comienza con un número y luego obtener todos los siguientes números hasta el primer carácter no numérico?

var strings = new List<string>{"2009 Arrears","2008 Arrears","2008 Arrears Interest","2009 Arrears Interest"}; 

y quieren que los resultados ordenados así:

  1. "2009 atrasos"
  2. "2009 Interés deudas"
  3. "2008" atrasos
  4. "2008 interés deudas"

Parece que necesito crear una función para ver si la cadena comienza con un número. Si es así, la función obtendrá todos los números hasta el primer carácter y ordenará el resultado numérico descendente y luego ordenará el resto de los caracteres ascendentes. Tengo problemas para escribir un método que obtenga todos los números iniciales en una cadena. ¿Cuál sería una manera eficiente de hacer eso?

+0

Puede estar interesado en esto: http://stackoverflow.com/questions/248603/natural-sort-order-in-c –

Respuesta

7
public int GetLeadingNumber(string input) 
{ 
    char[] chars = input.ToCharArray(); 
    int lastValid = -1; 

    for(int i = 0; i < chars.Length; i++) 
    { 
     if(Char.IsDigit(chars[i])) 
     { 
      lastValid = i; 
     } 
     else 
     { 
      break; 
     } 
    } 

    if(lastValid >= 0) 
    { 
     return int.Parse(new string(chars, 0, lastValid + 1)); 
    } 
    else 
    { 
     return -1; 
    } 
} 

Aunque esto sería estrictamente ser el más eficiente, las soluciones de expresiones regulares ofrecidos por otros carteles es, obviamente, más concisa y puede ser más claro, dependiendo de cuánto procesamiento va a hacer en la cadena.

7

una expresión regular sería dividir este bien:

var match = Regex.Match(text, @"^(\d+) (.*)$"); 

Entonces match.Groups[0].Value es el año, y match.Groups[1].Value es el título ("atrasos", "Interés deudas", etc)

Puede utilizar LINQ para aplicar el tipo (descendente año, título ascendente):

string[] titles = new[] { "2008 Arrears", "2009 Arrears" }; 

var sortedTitles = 
    from title in titles 
    let match = Regex.Match(title, @"^(\d+) (.*)$") 
    orderby match.Groups[0].Value descending, match.Groups[1].Value 
    select title; 

listBox.ItemsSource = sortedTitles.ToArray(); // for example 

una expresión regular puede no ser la solución más rápida; aquí es una alternativa que todavía está muy bien y limpia con LINQ:

var sortedTitles = 
    from title in titles 
    let year = new string(title.TakeWhile(ch => char.IsDigit(ch)).ToArray()) 
    let remainder = title.Substring(year.Length).Trim() 
    orderby year descending, remainder 
    select title; 
+0

Tenga en cuenta que esta expresión requerirá que los números sean seguidos por un espacio (a menos que el Regex se crea/invoca con la opción 'IgnoreWhitespace'). –

+0

Sí - Supuse que el espacio es un elemento garantizado de la cadena. –

Cuestiones relacionadas