2011-07-26 45 views
0

我有一個RichTextBox,看起來與此類似:C# - 排序字符串

TEXT TEXT-1  227.905 174.994 180 1111 
TEXT DIFTEXT 227.905 203.244 180 9999 
TEXT DIFTEXT2 242.210 181.294 180 2222 
TEXT TEXT-2  236.135 198.644 90 ABC1111 
TEXT SOMETEXT 250.610 201.594 0 DDDD 
TEXT OTHERTEXT 269.665 179.894 180 4444 
TEXT OTHERTEXT 269.665 198.144 180 1111 

而且我想給它一個特殊的排序。比方說,我想最後一個值對它進行排序在這個序列中(第6列)

1111,2222,4444,9999,DDDD

,然後排序它其次第2列按字母順序排列。

所以更新的文件應該是這樣的注:由於沒有排序爲「ABC1111」它匹配的1111,而不是

TEXT OTHERTEXT 269.665 179.894 180 1111 
TEXT TEXT-1  227.905 174.994 180 1111 
TEXT TEXT-2  236.135 198.644 90 ABC1111 #See note above 
TEXT DIFTEXT2 242.210 181.294 180 2222 
TEXT OTHERTEXT 269.665 198.144 180 4444 
TEXT DIFTEXT 227.905 203.244 180 9999 
TEXT SOMETEXT 250.610 201.594 0 DDDD 

,一旦有這種格式,我想把它寫回RichTextBox

  • 我該怎麼做?
+3

這篇文章是如何形成的?如果它只是給你這樣,好的。但是,如果你自己組成它,最好使用意識到所涉及的字段的對象進行排序。換句話說,在將數據作爲字符串轉出之前對其進行排序。 –

+2

列固定寬度嗎?列總會被一個或多個空格隔開嗎?列將包含空格嗎?你是否想按ASCII順序排列第六列(例如1,10,11,12 ... 2,3等)或數字順序(1,2,3 .... 9,10,11)?小於4位有效數字的值是否爲前導零?第6列中的所有非數字字符都被忽略了嗎?如果是這樣,爲什麼DDDD的線路出現在哪裏?我認爲這裏需要更多的細節,因爲有很多不明確的地方! – Bryan

+0

@馬特格里爾:不幸的是這件事給我的感覺。這就是爲什麼我不確定如何處理它。 :( – theNoobGuy

回答

2

TextBox類已經爲您提供了一行數組,無需任何工作。 Array.Sort將允許您傳入自己的代碼來比較行。我想不出一種優雅的方式來實現尷尬的排序規則,但我解決你的問題的方式看起來像下面的代碼。請注意,您需要將行數組拉出到temp變量中,以便您可以將其設置回去,否則不會調用setter,並且不會更新文本框。

private static void SortRichTextBox(RichTextBox richTextBox) 
{ 
    var lineArray = richTextBox.Lines; 
    Array.Sort(lineArray, delegate(string a, string b) 
    { 
     // I omitted Important corner cases like malformed lines, 
     // empty strings, and nulls. 

     // Additional sort cases can be added to the array as needed. 
     var sortOrder = new[] { "1111", "2222", "4444", "9999", "DDDD" }; 
     var aTokens = a.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); 
     var bTokens = b.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); 

     var aSignifier = Array.FindIndex(sortOrder, item => aTokens[5].Contains(item)); 
     var bSignifier = Array.FindIndex(sortOrder, item => bTokens[5].Contains(item)); 

     // This is where your first rule is being implemented, based on the data 
     // from the last column. The math is unimportant, what matters is the 
     // return being positive vs. negative vs. zero. 
     if (aSignifier != bSignifier) 
      return aSignifier - bSignifier; 

     // This is where your second rule is being implemented, as a backup when 
     // the result from the first rule indicates equality. We're just falling 
     // through to ordinary string comparison on the second column. 
     return aTokens[1].CompareTo(bTokens[1]); 
    }); 

    // We want to call the setter to get the textbox to update. 
    richTextBox.Lines = lineArray; 
} 

我測試了這個,它看起來像是起作用,至少在你的一個樣本數據集中。

+0

如果我有更多需要排序的案例:比如'3333','5555','6666','7777' ..等等,我會只創建更多的** if語句並將它們放入正確的「返回」值的順序? – theNoobGuy

+0

此外,還有一個關於超出範圍的索引錯誤'var bSignifier = GetSignifier(bTokens [5]);' – theNoobGuy

+0

那麼,是否只有少數情況需要排序?因爲這是我最初如何閱讀你的問題。如果這是一個普遍的規則,那麼我會寫一點不同。一般規則是什麼?如果有數字,按數字排序,如果沒有數字,按字母排序? –

0

銘記含糊我的評論凸顯。您可以將字符串解析爲一組對象(根據數據結構,String.SplitString.Substring可能會幫助您。

然後使用Array.Sort(首先由屬性表示第2列,然後是第6列)對數組進行排序,如示例here對自定義類型的數組進行排序。

爲您的課程創建一個.ToString方法,將每個對象轉換回正確的格式。

+0

好吧,我正在使用'string [] sortedOneRichTextBox = OneRichTextBox.Text.Split('\ n');' – theNoobGuy

+0

這會將你的文本分割成單獨的對象,但我正在考慮更多地分裂每個對象的單獨屬性。即'myObject.Field1 = myString.SubString(0,6).Trim(); myObject.Field2 = myString.SubString(6,11).Trim();'等 – Bryan

+0

我對SubString不熟悉。你有更具體的例子,你可以告訴我嗎?另外,如果我使用'String.Split'拆分文本,我可以使用sortedOneRichTextBox [5]值對它們進行排序嗎?然後通過sortedOneRichTextBox [1]值?如果是這樣,我怎麼能這樣做? – theNoobGuy

0

如果您將它們轉換爲對象,可以使用linq來排序它們。

http://msdn.microsoft.com/en-us/library/bb383982.aspx

假設你可以讓他們進入的對象,你可以在 爲了利用 從, 選擇

要解決的問題abc1111,我會創造你是一個單獨的屬性排序只包含1111.

此外,請記住接受答案。

1
static void Main(string[] args) 
{ 
    string input = 
     "TEXT TEXT-1  227.905 174.994 180 1111\n" + 
     "TEXT DIFTEXT 227.905 203.244 180 9999\n" + 
     "TEXT DIFTEXT2 242.210 181.294 180 2222\n" + 
     "TEXT TEXT-2  236.135 198.644 90 ABC1111\n" + 
     "TEXT SOMETEXT 250.610 201.594 0 DDDD\n" + 
     "TEXT OTHERTEXT 269.665 179.894 180 4444\n" + 
     "TEXT OTHERTEXT 269.665 198.144 180 1111"; 

    string[] lines = input.Split('\n'); 
    string[][] grid = new string[lines.Length][]; 
    for (int i = 0; i < lines.Length; i++) 
    { 
     grid[i] = lines[i].Split((char[])null, StringSplitOptions.RemoveEmptyEntries); // split on whitespace 
    } 

    IEnumerable<string[]> results = grid 
     .OrderBy(gridRow => TransformColumn6(gridRow[5])) 
     .ThenBy(gridRow => gridRow[1]); 

    foreach (string[] gridRow in results) 
    { 
     Debug.WriteLine(string.Join(" ", gridRow)); 
    } 
} 

private static string TransformColumn6(string input) 
{ 
    if (char.IsDigit(input[0])) 
    { 
     // string is a bunch of numbers, use as-is. 
     return input; 
    } 

    int digitIndex = input.IndexOfAny(new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }); 
    if (digitIndex == -1) 
    { 
     // string has no numbers, use as-is, will be sorted in alphabetical order after all the numbers. 
     return input; 
    } 

    // string has a number, remove the stuff at the beginning. 
    return input.Substring(digitIndex); 
} 

結果(列格式手動添加):

TEXT OTHERTEXT 269.665 198.144 180 1111 
TEXT TEXT-1 227.905 174.994 180 1111 
TEXT TEXT-2 236.135 198.644 90 ABC1111 
TEXT DIFTEXT2 242.210 181.294 180 2222 
TEXT OTHERTEXT 269.665 179.894 180 4444 
TEXT DIFTEXT 227.905 203.244 180 9999 
TEXT SOMETEXT 250.610 201.594 0 DDDD 

如果排序的最後一列的規則得到更加複雜,那麼你可能想實現一個自定義的比較,而不是使用默認的字符串比較。