循环迭代数组字符串

时间:2017-05-04 16:15:01

标签: c# visual-studio for-loop

我目前正试图解决标题资本化问题。我有一个方法,它接受一个句子,将其分成单词,将单词与单词检查列表进行比较。

根据此检查列表,如果它们在列表中,我会小写单词。大写任何不在列表中的单词。第一个和最后一个字总是大写的。

这是我的方法:

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是小写的。我如何解决这个问题的任何提示?

4 个答案:

答案 0 :(得分: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循环的第六次,它成功完成测试并以小写字母写成,所有其他的都失败,因此它被大写。

答案 1 :(得分: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]));
    }
}

输出:

  

我喜欢解决问题而且很有趣

答案 2 :(得分: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中的查找可以在没有特殊比较的情况下完成。因为单词已经是小写的,所以如果单词不必大写,则不必再进行大写。

答案 3 :(得分: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字词的字符串,则不会将其转换为小写,因为{ {1}}方法(或在其他答案的情况下,Equals方法)默认情况下进行区分大小写的比较。因此,您可能希望将不区分大小写的比较器传递给该方法。
  3. 您不需要对第一个和最后一个单词进行单独检查。您可以在循环体中使用单个Contains语句进行这些检查
  4. 所以,这就是我要做的事情:

    if