2017-05-04 115 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中的查找可以在没有特殊比较的情况下完成。因为这些单词已经是小写字母,所以如果单词不需要大写,就不必再做了。