2017-05-04 114 views
0

我正在嘗試解決標題大寫問題。我有一種方法可以接受一個句子,將其分解成單詞,將這些單詞與單詞的檢查單進行比較。數組字符串的循環迭代

基於此檢查列表,如果它們在列表中,我將小寫字母。大寫字母不在列表中。第一個和最後一個單詞總是大寫。

這裏是我的方法:

public string TitleCase(string title) 
{ 
     LinkedList<string> wordsList = new LinkedList<string>(); 
     string[] listToCheck = { "a", "the", "to", "in", "with", "and", "but", "or" }; 
     string[] words = title.Split(null); 
     var last = words.Length - 1; 
     var firstWord = CapitalizeWord(words[0]); 
     var lastWord = CapitalizeWord(words[last]); 

     wordsList.AddFirst(firstWord); 
     for (var i = 1; i <= last - 1; i++) 
     { 
      foreach (var s in listToCheck) 
      { 
       if (words[i].Equals(s)) 
       { 
        wordsList.AddLast(LowercaseWord(words[i])); 
       } 
       else 
       { 
        wordsList.AddLast(CapitalizeWord(words[i])); 
       } 
      } 
     } 
     wordsList.AddLast(lastWord); 
     var sentence = string.Join(" ", wordsList); 
     return sentence; 
    } 

與實例運行此並期待結果:

var result = TitleCase("i love solving problems and it is fun"); Assert.AreEqual("I Love Solving Problems and It Is Fun", result);

我得到相反:

"I Love Love Love Love Love Love Love Love Solving Solving Solving Solving Solving Solving Solving Solving Problems Problems Problems Problems Problems Problems Problems Problems And And And And And and And And It It It It It It It It Is Is Is Is Is Is Is Is Fun" 

如果你仔細觀察一個and是小寫。我如何解決這個問題的任何提示?


+0

在'for'設置一個斷點,然後調試代碼然後按下「F10」來瀏覽它,看看發生了什麼。 – Quantic

+0

使用調試器並單步執行代碼。隨時留意你的單詞列表是如何增長的,並且你會看到發生了什麼問題...... – elgonzo

回答

0

當您檢查每個單詞時,您正在做一些額外的循環操作,並且只要您找到匹配項,您就不會退出循環(因此您要在每次檢查時添加該單詞)。要解決您的特定代碼這個問題,你會做這樣的事情:

for (var i = 1; i <= last - 1; i++) 
{ 
    bool foundMatch = false; 

    foreach (var s in listToCheck) 
    { 
     if (words[i].Equals(s)) 
     { 
      foundMatch = true; 
      break; 
     } 
    } 

    if (foundMatch) 
    { 
     wordsList.AddLast(LowercaseWord(words[i])); 
    } 
    else 
    { 
     wordsList.AddLast(CapitalizeWord(words[i])); 
    } 
} 

然而,有一個更簡單的方法,其他的答案都提供了。但我想指出一些其他的東西:

  1. 您正在創建一個不必要的LinkedList。您已經有了可以在words數組中操作的單詞列表,因此只需使用它即可節省一些內存。
  2. 我認爲在你的代碼中(和一些答案中)有一個錯誤,如果某人傳入一個字符串中間帶有大寫字母A的字符,它將不會被轉換爲小寫字母,因爲Equals方法(或在其他答案的情況下,Contains方法)默認情況下進行區分大小寫的比較。所以你可能想要將一個不區分大小寫的比較器傳遞給該方法。
  3. 你不需要對第一個和最後一個單詞進行單獨的檢查。你可以只是有一個單一的if語句這些檢查在循環

這樣的身體,這裏就是我會做:

public static string TitleCase(string title) 
{ 
    var listToCheck = new[]{ "a", "the", "to", "in", "with", "and", "but", "or" }; 
    var words = title.Split(null); 

    // Loop through all words in the array 
    for (int i = 0; i < words.Length; i++) 
    { 
     // If we're on the first or last index, or if 
     // the word is not in our list, Capitalize it 
     if (i == 0 || i == (words.Length - 1) || 
      !listToCheck.Contains(words[i], StringComparer.OrdinalIgnoreCase)) 
     { 
      words[i] = CapitalizeWord(words[i]); 
     } 
     else 
     { 
      words[i] = LowercaseWord(words[i]); 
     } 
    } 

    return string.Join(" ", words); 
} 
+0

確實。我試着用'var result = TitleCase(「你是一隻雙腳飛行嗎?」); Assert.AreEqual(「爲什麼鳥會飛?」,結果);'並且與「A」有問題。上面的代碼解決了這個問題。謝謝。 –

0

的問題是在foreach循環中,要爲每個單詞做8個檢查(在listToCheck陣列的長度) - 和每次加字到列表中。我也建議使用LINQ查詢,所以它應該是這樣的:

 for (var i = 1; i <= last - 1; i++) { 

      if(listToCheck.Contains(words[i])) 
       wordsList.AddLast(LowercaseWord(words[i])); 
      else 
       wordsList.AddLast(CapitalizeWord(words[i])); 
     } 

此外,第六「和」被小寫的原因是因爲它是listToCheck數組中的第六個字。在第六次圍繞foreach循環時,它成功通過了測試並以小寫形式寫入,其他所有的都失敗了,所以它被大寫。

0

你有一個循環弄亂的東西了內循環,簡化了代碼只有一個循環:

for (var i = 1; i <= last - 1; i++) 
{ 
    // No inner loop 
    // Use the .Contains() method to see if it's a key word 
    if (listToCheck.Contains(words[i])) 
    { 
     wordsList.AddLast(LowercaseWord(words[i])); 
    } 
    else 
    { 
     wordsList.AddLast(CapitalizeWord(words[i])); 
    } 
} 

輸出:

我愛解決問題,很好玩

0

正如其他答案中所提到的,循環內的循環不會退出。 只是一個建議,使用LINQ,你可以結合檢查第一個和最後一個字(通過指數),並檢查ListToCheck在一起:

public string TitleCase(string title) 
{   
    string[] listToCheck = { "a", "the", "to", "in", "with", "and", "but", "or" }; 
    string[] words = title.Split(null); 
    var last = words.Length - 1; 
    return string.Join(" ", words.Select(w=>w.ToLower()).Select(((w,i) => i == 0 || i == last || !listToCheck.Contains(w) ? CapitalizeWord(w) : w))); 
} 

注意,在該方案中,第一Select確保所有的單詞都是小寫的,因此listToCheck中的查找可以在沒有特殊比較的情況下完成。因爲這些單詞已經是小寫字母,所以如果單詞不需要大寫,就不必再做了。