2009-09-30 4 views
5

J'ai une obligation de trier des chaînes qui contiennent des données comme ceci:Comment déterminer efficacement si une chaîne commence par un nombre, puis obtenir tous les numéros suivants jusqu'à ce que le premier caractère non numérique?

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

Et ils veulent que les résultats ordonnés comme ceci:

  1. « 2009 Arriérés »
  2. « 2009 des intérêts débiteurs »
  3. "2008" arriérés
  4. "intérêt 2008 arriérés"

Il semble que j'ai besoin de créer une fonction pour voir si la chaîne commence par un nombre. Si c'est le cas, la fonction mettra tous les nombres en place jusqu'au premier caractère et triera le résultat numérique en descendant, puis triera les caractères restants en montant. J'ai du mal à essayer d'écrire une méthode qui obtient tous les nombres de départ dans une chaîne. Qu'est-ce qui serait un moyen efficace de faire cela?

+0

Vous pouvez être intéressé par ceci: http://stackoverflow.com/questions/248603/natural-sort-order-in-c –

Répondre

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; 
    } 
} 

Bien que cela serait strictement les plus efficaces, les solutions d'expressions régulières offertes par d'autres affiches est évidemment plus concis et pourrait être plus clair, selon combien de traitement vous ferez sur la chaîne.

7

Un regex diviserait ce gentiment:

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

Alors match.Groups[0].Value est l'année, et match.Groups[1].Value est le titre ("Arriérés", "des intérêts débiteurs", etc.)

Vous pouvez utiliser LINQ d'appliquer le genre (année en ordre décroissant, titre croissant):

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 

Un regex peut ne pas être la solution la plus rapide; voici une alternative qui est toujours gardé agréable et propre avec 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

Notez que cette expression exigera que les nombres soient suivis d'un espace (à moins que le Regex est créé/invoqué avec l'option 'IgnoreWhitespace'). –

+0

Oui - J'ai supposé que l'espace est un élément garanti de la chaîne. –

Questions connexes