2009-09-30 11 views
5

Böyle veri içeren bazı dizeleri sıralamak için bir gereksinim vardır:Bir dizenin bir sayı ile başlayıp başlamadığına ve ardından sayısal olmayan ilk karaktere kadar aşağıdaki tüm sayıları nasıl alacağınızı verimli bir şekilde nasıl belirleyebilirim?

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

Ve sonuç böyle emretti istiyorum:

  1. "2009 borçları"
  2. "2009 borçları faiz"
  3. "2008 borçları"
  4. "2008 borçları faiz"

Dizenin bir sayı ile başlayıp başlamadığını görmek için bir işlev oluşturmam gerekiyor gibi görünüyor. Eğer öyleyse, işlev ilk karaktere kadar tüm sayıları alacak ve sayısal sonucu azalan olarak sıralayacak ve ardından kalan karakterleri artan şekilde sıralayacaktır. Bir dizede tüm başlangıç ​​numaralarını alan bir yöntem yazmaya çalışırken sorun yaşıyorum. Bunu yapmanın verimli bir yolu ne olurdu?

+0

Bu şununla ilgini çekebilir: http://stackoverflow.com/questions/248603/natural-sort-order-in-c –

cevap

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

, diğer posterler tarafından sunulan düzenli ifade çözümleri açıkçası daha özlü ve bağlı çok açık: hala burada LINQ ile güzel ve temiz tutulur bir alternatiftir ipte ne kadar işlem yapacağınız.

7

bir regex güzel bu kadar bölünmüş olacaktır: Sonra

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

match.Groups[0].Value yıl ve match.Groups[1].Value başlık ("borçları", "borçları faiz", vs)

Sen LINQ kullanabileceği başka sıralama (yıl inip, başlık artan) uygulamak:

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 

bir düzenli ifade hızlı çözüm olmayabilir; Bu kesinlikle en verimli olacağını rağmen

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

Bu ifadenin sayıların bir boşlukla takip edilmesini gerektirdiğini unutmayın (Regex dışında) "IgnoreWhitespace" seçeneği ile oluşturulur/çağrılır. –

+0

Evet - Alanın dizgenin garantili bir öğesi olduğunu varsaydım. –

İlgili konular