Подсчет слов с числом символов более x в строке в C # с использованием лямбда-выражений - PullRequest
0 голосов
/ 30 мая 2019

Я написал программу для подсчета слов в предложении, которые имеют 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";

теперь давайте предположим, что мне нужно считать каждое 3-е слово в каждой 2-й строке и считать, если в этих отфильтрованных словах есть 2 или более гласных. Если это условие соответствует, вернуть соответствующее количество слов и общее количество строк, содержащих эти соответствующие слова.

например. с критериями выбора каждой 2-й строки, отфильтрованные строки будут {2, 4, 6}. Аналогично, каждое 3-е слово в этой отфильтрованной строке будет строкой 2: {"the", "Wars"}, для строки 4: {"of", "before"} и для строки 6: {"be", "after"} ,

Для этих отфильтрованных слов совпадающие слова с 2 или более гласными будут {"до"} в строке номер 4 и слова {"после"} в строке 6. Таким образом, конечный результат будет wordCount = 2, и так как эти слова из строки 4 и 6, так что общее количество lineCount = 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, но не уверен, как их использовать здесь.

Все комментарии приветствуются.

Ответы [ 2 ]

1 голос
/ 30 мая 2019

Сначала отфильтруйте строки, используя «предикат» в предложении «где», чтобы получить каждую 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);
0 голосов
/ 30 мая 2019

Разумно ли помещать все в один большой запрос LINQ? Это затруднит понимание вашего кода, его тестирование, внесение изменений или повторное использование его частей.

Рассмотрите возможность написания отдельных LINQ-подобных функций, которые выполняют только часть вашего кода. Это называется методом расширения. См. Расширение методов расширения

Мне нужно считать каждое 3-е слово в каждой 2-й строке и считать, если в этих отфильтрованных словах есть 2 или более гласных. Если это условие соответствует, вернуть количество совпадающих слов и общее количество строк, содержащих эти совпадающие слова.

Итак, создайте функции:

  • Ввод: строка; Вывод: строка, разделенная на последовательность строк
  • Ввод: последовательность строк; Вывод: последовательность каждой 2-й строки (или каждой n-й строки)
  • Ввод: строка; вывод: слова в строке
  • Ввод: последовательность слов; вывод: третье слово в последовательности (или каждое n-е слово)
  • Ввод: слово; вывод: количество гласных в слове

Большинство из них довольно просты:

IEnumerable<string> ToLines(this text)
{
    // TODO: check text not null
    using (var reader = new StringReader(text))
    {
        var line = reader.ReadLine();
        while (line != null)
        {
            yield return line;
            line = reader.ReadLine();
        }
    }
}

IEnumerable<string> KeepEvery2ndLine(this IEnumerable<string> lines)
{
    // TODO: check lines not null
    int lineNr = 0;
    foreach (var line in lines
    {
        ++lineNr;
        if (lineNr%2 == 0)
            yield return line;
    }
}

IEnumerable<string> ToWords(this string line)
{
    // TODO: check line not null
    // when is a word a word? do you need to consider tabs? semicolons?
    // is a number like 12 a word?
}

Совет: используйте Regex, чтобы разделить строку на слова. См как разбить строку в словах
Кстати: если слово «12», сколько гласных у него: ноль или два? («двенадцать» имеет две гласные)

Я не буду писать все функции. Вы получите суть.

Поскольку вы разделяете свою задачу на более мелкие задачи, довольно легко понять, что должна делать каждая функция, ее легко реализовать, легко проверить, легко изменить.

Получив их, ваш запрос довольно прост:

var result = inputText.ToLines()
                      .KeepEvery2ndLine()
                      .ToWords()
                      .KeepEvery3rdWord()
                      .CountVowels();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...