C#根据输入字符串查找子字符串

本文关键字:字符串 查找 输入 | 更新日期: 2023-09-27 18:21:39

我是C#的新手,所以我没有太多经验。

对于一个简单的体验项目,我需要从一个句子中找到与我得到的输入相似的关键词。

现在看来,解决方案比我想象的要复杂得多,所以请原谅我缺乏经验或知识。

我从数据库中得到一个字符串,它可以有任意数量的字母,其余的都是数字,但字符串中的字符总数必须用于匹配。

string ThisIsTheTemplateToLookFor = "AB12345678"

我有一个字符串,里面有一些文本:

string FromThisStringINeedToFind = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s and here comes the text to find AB54925871";

对于ThisIsTheTemplateToLookFor,可能必须构建regex命令才能找到类似的文本片段。

所以它需要找到:

AB12345678
AB87654321
AB67812345
...
etc
...

正则表达式必须从示例字符串中查找两个字母和8个数字。或者在不同的情况下,ThisIsTheTemplateToLookFor字符串可以是A1234,正则表达式应该找到A1234A4321A3910等。

或者,正如Tim Schmelter所建议的,也许是Levenstein距离算法

对不起,我的语言不是以英语为母语的

我认为他的观点是,搜索字符串与应该找到的字符串在细微且尚未枚举的方面有所不同。在本例中,搜索字符串是AB12345678,但应该发现的字符串是AB54925871

我的猜测是,如果搜索字符串是AB12345678,那么应该可以找到以任何顺序包含这10个字符的任何10个字符子字符串短柄

  • 在第一个例子中,AB和任何8个数字都应该给出一个结果
  • 在第二个例子中,A和任意4个数字都应该给出一个结果

C#根据输入字符串查找子字符串

既然您已经在第一个问题中澄清了要求,但由于它仍然关闭,我无法发布答案,我将在这里投入我的两分钱。

您不需要正则表达式,下面的内容可以根据需要工作。您的样品:

string sample = "AB12345678";
string subject = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s and here comes the text to find AB54925871";

现在你想在句子中找到具有相同Length的单词,该单词以相同的字母开头,以相同数量的(连续)数字结尾:

string letters = string.Join("", sample.TakeWhile(Char.IsLetter));
int countDigits = sample.SkipWhile(Char.IsLetter).TakeWhile(Char.IsDigit).Count();

您可以使用以下LINQ查询:

var matchingWords = subject.Split()  // splits by spaces, tabs and new-lines
    .Where(word => sample.Length == word.Length
        && letters == string.Join("", word.TakeWhile(Char.IsLetter))
        && countDigits == word.SkipWhile(Char.IsLetter).TakeWhile(Char.IsDigit).Count());
string word = matchingWords.FirstOrDefault();  // AB54925871

如果没有找到匹配的单词,则返回null

如果你想找到所有并用逗号分隔:

string allWords = string.Join(",", matchingWords);

根据您的问题陈述,我们在这里不是在谈论火箭科学:只需创建一个类似的工厂方法,即可满足您的需求:

static Regex CreateRegularExpressionFromTemplate( string template )
{
  StringBuilder sb = new StringBuilder() ;
  foreach( char c in template )
  {
    if      ( char.IsLetter(      c ) ) sb.Append( @"'p{L}" ) ;
    else if ( char.IsNumber(      c ) ) sb.Append( @"'d"    ) ;
    else if ( char.IsWhiteSpace(  c ) ) sb.Append( @"'s"    ) ;
    else if ( char.IsPunctuation( c ) ) sb.Append( @"'p{P}" ) ;
    else throw new ArgumentOutOfRangeException("template") ;
  }
  string pattern = sb.ToString() ;
  Regex rx = new Regex( pattern ) ;
  return rx ;
}

这将使

@"AB12345678"

进入这个

@"'p{L}'p{L}'d'd'd'd'd'd'd'd"

然后你可以做之类的事情

Regex rx = CreateRegularExpressionFromTemplate( "AB12345678" ) ;
Match m  = rx.Match( "This is zX98320987 speaking." ) ;
if ( m.Success)
{
  Console.WriteLine( "We matched '{0}'" , m.Value ) ;
}
else
{
  Console.WriteLine( "no match found" ) ;
}

并获得预期的

We matched 'zX98320987'

编者按:如果你需要在单词边界上匹配,你可以简单地添加适当的正向向后看和正向向前看断言:

static Regex CreateRegularExpressionFromTemplate( string template )
{
  StringBuilder sb = new StringBuilder() ;
  sb.Append( @"(?<=(^|'W))" ) ; // require the match to at the beginning of a word
  foreach( char c in template )
  {
    if      ( char.IsLetter(      c ) ) sb.Append( @"'p{L}" ) ;
    else if ( char.IsNumber(      c ) ) sb.Append( @"'d"    ) ;
    else if ( char.IsWhiteSpace(  c ) ) sb.Append( @"'s"    ) ;
    else if ( char.IsPunctuation( c ) ) sb.Append( @"'p{P}" ) ;
    else throw new ArgumentOutOfRangeException("template") ;
  }
  sb.Append( @"(?=($|'W))" ; // require the match to end at the end of a word
  string pattern = sb.ToString() ;
  Regex rx = new Regex( pattern ) ;
  return rx ;
}