首页 > 解决方案 > 使用 lambda 表达式计算 C# 中字符串中超过 x 个字符的单词

问题描述

我编写了一个程序来计算句子中匹配字符数为 x 的单词。输入字符串是一个多行字符串,我只需要考虑基于给定标准的备用行。同样在那些过滤的行中,我需要进一步选择替代词,然后检查这些过滤的词是否与相交的字符匹配。

例如,假设我有一个如下输入字符串,并且需要找到其中包含 2 个或更多元音的单词:

string myString = "1.In order to get a Disneyland ticket
2.that includes the new Star Wars land
3.you must stay at a Disney hotel 
4.the night of or night before your visit. 
5.Day passes without a hotel 
6.reservation will be available after June 23";

现在假设我需要计算每 2 行中的每 3 个单词,并计算这些过滤后的单词中是否包含 2 个或更多元音。如果匹配此条件,则返回匹配字数和包含这些匹配字的总行数。

例如,使用每 2 行选择的标准,过滤后的行将是 {2,4,6}。同样,这些过滤行中的每个第 3 个单词将是第 2 行:{“the”,“Wars”},第 4 行:{“of”,“before”},第 6 行:{“be”,“after”} .

对于这些过滤后的单词,具有 2 个或更多元音的匹配单词将是第 4 行中的 {"before"} 和第 6 行中的单词 {"after"}。因此最终输出将是 wordCount = 2 并且因为这些单词来自行4 和 6 所以总行数 = 2。

我使用生成所需输出的嵌套 for 循环编写了以下代码。

public static void Main(string[] args)
    {
        int vowelCount = 2; // match words with 2 or more vowels
        int skipWord = 3; // Consider every 3rd word only
        int skipLine = 2; // Consider every 2nd line only
        int wordCount = 0;
        int lineCount = 0;

        string myString = @"1.In order to get a Disneyland ticket
2.that includes the new Star Wars land
3.you must stay at a Disney hotel 
4.the night of or night before your visit. 
5.Day passes without a hotel 
6.reservation will be available after June 23";";

        List<string> myList = myString.Split(Environment.NewLine).ToList();
        List<string> lineWords = new List<string>();
        char[] vowels = {'a', 'e', 'i', 'o', 'u'};

        for (int i = skipLine; i <= myList.Count; i += skipLine)
        {
            int origWordCount = wordCount;
            lineWords = myList[i - 1].Split(' ').ToList();
            for (int j = skipWord; j <= lineWords.Count; j += skipWord)
            {
                char[] wordArr = lineWords[j-1].ToLower().ToCharArray();
                int match = vowels.Intersect(wordArr).Count();
                if (match >= vowelCount)
                    wordCount++;                 
            }
            if (wordCount > origWordCount)
                lineCount++;
        }

        Console.WriteLine("WordCount : {0}, LineCount : {1}", wordCount, lineCount);

上面的代码效果很好,但想知道是否有办法在没有嵌套循环的情况下做到这一点。我读到了 linq 和 lambda 表达式,但不知道如何在这里使用它们。

感谢所有评论。

标签: c#linqlambda

解决方案


首先使用 'where' 子句中的 'predicate' 过滤行,如下所示获取每 2 行:

List<string> lines = myString.Split(Environment.NewLine).Where((l,index) => index % 2 != 0).ToList();

然后你可以得到如下结果:

foreach (var line in lines)
{
    // Get every 3rd word in the line
    var thirdWords = line.Split(' ').Where((w,index) => index % 3 == 2).ToList();

    // Get words with 2 or more vowels in it. 
    // Have you tested words that have same vowel twice?
    var matchWords = thirdWords.Where(w => w.Intersect(vowels).Count() >= vowelCount).ToList();

    //if words with vowels found, update 'wordCount' and 'lineCount' 
    if (matchWords.Any()) {
        wordCount = wordCount + matchWords.Count;
        lineCount++;
    }
}
Console.WriteLine("WordCount : {0}, LineCount : {1}", wordCount, lineCount);

推荐阅读