【问题标题】:Search a string for particular characters and extract the words they appear (C#)在字符串中搜索特定字符并提取它们出现的单词 (C#)
【发布时间】:2019-08-09 21:24:28
【问题描述】:

有谁知道我如何在字符串中搜索特定字符并提取它们所在的实际单词?如果一个单词确实包含特定字符,我如何根据该单词拆分字符串?这是我正在尝试做的一个例子。输入语句(字符串)为:"We both arrived at the garage this morning"。然后我想在该字符串中搜索所有出现的字符"ar"。如果任何单词包含这两个字母,我想根据这些单词拆分字符串。所以在这个例子中,分割字符串看起来像:

Element 1: "We both"
Element 2: "arrived"
Element 3: "at the"
Element 4: "garage"
Element 5: "this morning"```

【问题讨论】:

    标签: c# string split


    【解决方案1】:

    可能有更好的方法,但是看看这个问题,我创建了自己的拆分函数。

    函数的快速分解如下。

    • 查找split string 的第一个匹配项,在本例中为ar
      • 如果没有出现,则返回输入
    • 在此事件发生后暂时删除所有内容
      • 在我们的第一种情况下,这将给我们留下字符串"We both "
    • 查找最后出现的空格以仅提供完整的单词
      • 这会给我们"We both"
      • 如果没有找到任何匹配项,那么我们就有了最后的结果,只需返回从split string 拆分的字符串
    • 将此添加到列表中
    • 返回字符串"arrived at the garage this morning"的剩余部分,寻找下一个空格。这将为我们提供包含 Split String 的单词并将其添加到列表中
    • 去掉这个词剩下的部分就是"at the garage this morning"
    • 递归调用此函数,直到找不到更多ars
    private List<string> SplitOnFullWords(string input, string split)
    {
        List<string> result = new List<string>();
    
        int firstIndexOfSplit = input.IndexOf(split);
    
        // we have found an occurence of the split string, remove everything after this.
        if (firstIndexOfSplit >= 0)
        {
            string splitString = input.Substring(0, firstIndexOfSplit);
    
            // Find the last occurance of a space before this index; this will give us all full words before 
            int lastIndexOfSpace = splitString.LastIndexOf(' ');
    
            // If there are no sapces before this word then just add it and try for more
            if (lastIndexOfSpace >= 0)
            {
                // Add the words before the word containing the splitter string
                result.Add(splitString.Substring(0, lastIndexOfSpace));
    
                // Add the word contianing the splitter string
                string remainingString = input.Substring(lastIndexOfSpace + 1);
                int firstSpaceAfterWord = remainingString.IndexOf(' ');
    
                if (firstSpaceAfterWord >= 0)
                {
                    result.Add(remainingString.Substring(0, firstSpaceAfterWord));
    
                    // Look for more after the word containing the splitter string
                    string finalString = remainingString.Substring(firstSpaceAfterWord + 1);
                    result.AddRange(SplitOnFullWords(finalString, split));
                }
                else
                {
                    result.Add(remainingString);
                }
            }
            else
            {
                // Add the word contianing the splitter string
                int firstSpaceAfterWord = input.IndexOf(' ');
    
                if (firstSpaceAfterWord >= 0)
                {
                    result.Add(input.Substring(0, firstSpaceAfterWord));
    
                    // Look for more after the word containing the splitter string
                    string finalString = input.Substring(firstSpaceAfterWord + 1);
                    result.AddRange(SplitOnFullWords(finalString, split));
                }
                else
                {
                    result.Add(input);
                }
            }
        }
        else
        {
            // No occurences of the split string, just return the input
            result.Add(input);
        }
    
        return result;
    }
    

    并使用

    foreach (string word in SplitOnFullWords(inputWord, "ar"))
        Console.WriteLine(word);
    

    【讨论】:

    • 感谢您的帮助,您的解决方案非常适合我的示例。但是,当我将参数更改为"did you purchase the house", "ou"时,出现以下错误:ArgumentOutOfRangeException: Cannot be negative. Parameter name: length
    • 更新的代码 :) 如果最后一个单词是包含拆分字符串的单词,则无法处理 - 也将修复第一个单词;字面上的边缘情况:D哈哈
    • 非常感谢您花时间帮助我。您更新的代码有效,但奇怪的是对于此示例 ""aesthetically pleasing", "ae" 无效。我在控制台中得到一个空白结果?不知道有没有用?
    • 是的,我刚刚更新以修复它:D 两个边缘情况,第一个单词和最后一个单词没有被处理 :(。但现在他们应该是!
    • 如果句子的第一个单词包含分隔符,似乎代码“中断”?如果我将之前的示例轮换为“美观”,它会起作用!
    【解决方案2】:

    这是一个使用两个正则表达式的解决方案。第一个找到匹配词,第二个在匹配词上拆分字符串。

    string sentence = "We both arrived at the garage this morning";
    string search = "ar";
    
    // word boundary, optional characters, search term, optional characters again, word boundary.
    string regex = @"\b\w*(" + search + @")\w*\b";
    
    // find words matching the search term
    var foundWords = Regex.Matches(sentence, regex)
        .Cast<Match>()
        .Select(match => match.Value)
        .ToList();
    
    List<string> result = null;
    if (foundWords.Count == 0)
    {
        // If no words were found, use the original sentence.
        result = new List<string> { sentence };
    }
    else
    {
        // Create a split term containing the found words.
        var splitTerm = string.Join('|', foundWords.Select(w => "(" + w + ")"));
    
        // Split the sentence on the found words and trim the parts from spaces.
        result = Regex.Split(sentence, splitTerm)
            .Select(part => part.Trim())
            .ToList();
    }
    
    foreach (var part in result)
    {
        Console.WriteLine(part);
    }
    

    【讨论】:

      【解决方案3】:

      将句子拆分成单词,然后构建字符串列表,检查每个单词是否包含给定的字符。

      string sentence = "We both arrived at the garage this morning";
      string[] words = sentence.Split();
      List<string> results = new List<string>();
      
      string s = "";
      
      foreach (string word in words)
      {
          if (word.Contains("ar"))
          {
              if (s != "")
              {
                  results.Add(s.Trim());
                  s = "";
              }
              results.Add(word);
          }
          else
          {
              s += word + " ";
          }
      }
      if (s != "")
          results.Add(s);
      
      // results contains the desired strings.
      

      【讨论】:

        【解决方案4】:

        这是一种迂回的方式,但它可以完成工作。我将假设您通过由空格分隔的字符串来定义“单词”。

        var line = "We both arrived at the garage this morning";
        var keyword = "ar";
        

        上面将为您提供句子中的“单词”列表。

        下面是一个包含结果的string 列表,重要的是它在第一个索引处有一个空字符串。

        var resultList = new List<string>() { string.Empty };
        
        var parts = line.Split(' ').ToList();
        for (int i = 0; i < parts.Count; i++)
        {
            // If the word contains your keyword, add it as a new item in the list.
            // Next add new item that is an empty string.
            if (parts[i].Contains(keyword))
            {
                resultList.Add(parts[i]);
                resultList.Add(string.Empty);
            }
            // Otherwise, add the word to the last item, and then add a space at the end to separate words.
            else
            {
                resultList[resultList.Count - 1] = resultList[resultList.Count - 1] + parts[i] + " ";
            }
        }
        

        上面会导致一些单词包含尾随空格,所以你可以把它们剪掉。

        for (int i = 0; i < resultList.Count; i++)
        {
            if (resultList[i].EndsWith(" "))
                resultList[i] = resultList[i].TrimEnd(new char[] { ' ' });
        }
        

        【讨论】:

          【解决方案5】:

          可能不是完成此任务的最高性能方式 - 但这对我有用。

           static void Main(string[] args)
              {
                  // sets variables
                  string example = "We both arrived at the garage this morning";
                  string searchTerm = "ar";
                  var intermediateArray = new List<string>();
                  var answerArray = new List<string>();
                  var tempText = "";
          
                  //splits on " " to isolate words into list.
                  var exampleArray = example.Split(" ");
          
                  //loops through each word in original string
                  foreach(var word in exampleArray)
                  {
                      //if word contains search term, add it to the answer array
                      if (word.Contains(searchTerm))
                      {
                          tempText = "";
          
                          //loops through words that did not contain the search term 
                          //and adds them as a single string to the answer array.
                          foreach(var message in intermediateArray)
                          {   
                              tempText = tempText + message + " ";
                          }
          
                          answerArray.Add(tempText);
                          answerArray.Add(word);
                          intermediateArray.Clear();
          
                      }
                      //if word does not include search term, add it to the string 
                      //that will later be added.//
                      else
                      {
                          intermediateArray.Add(word);
                      }
                  }
          
                  // to demonstrate working as intended
                  foreach(var text in answerArray)
                  {
                      Console.WriteLine(text);
                  }
          
              }
          

          【讨论】:

          • 感谢您的帮助。对不起,我应该在我的原始帖子中提到,我不想在空格上分开。我只想在包含分隔符的单词上拆分字符串...对此感到抱歉。
          • 我的代码中的 answerArray(实际上是一个列表,因为我们不知道它会有多长)包含由包含“ar”的单词分割的每个字符串。所以在 answerArray[0] 我们有“We both”和 answerArray[1] 我们有“arrived”,依此类推。我正在通过空格进行拆分,以便能够搜索包含“ar”的单词,然后根据该单词重建每个字符串以获得最终结果。我不确定如何在不首先隔离单词的情况下查找单词是否包含“ar”。
          猜你喜欢
          • 2011-04-13
          • 1970-01-01
          • 1970-01-01
          • 2015-09-25
          • 2012-01-05
          • 2016-04-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多