正则表达式强制字符串中特定字符的上限
本文关键字:字符 字符串 正则表达式 | 更新日期: 2023-09-27 18:23:49
我有一个单词列表,我需要消除所有出现零次或不超过一次i
、零次或不超过两次出现的o
和零次或不超过三次出现的单词u
。
例如:
in
会起作用,但inside
不会。
on
和octopus
会起作用,但commotion
不会
到目前为止,我最好的猜测似乎并没有完成工作:
Regex regex = new Regex(@"i?|o{0,2}|u{0,3}");
lines = text.Where(x => regex.IsMatch(x)).ToArray(); // text is array containing the words
string[] text = new string[] { "in", "inside", "on", "octopus", "commotion" };
Regex regex = new Regex(@"(i.*){2}|(o.*){3}|(u.*){4}");
var lines = text.Where(x => !regex.IsMatch(x)).ToArray(); // text is array containing the words
foreach (var s in lines)
{
Console.WriteLine(s);
}
编辑
只有一个警告。由于回溯,此解决方案不会扩展到大量字母。为了改进缩放,必须禁用回溯:
Regex regex = new Regex(@"(?>.*?i){200}|(?>.*?o){300}|(?>.*?u){400}");
您的正则表达式仅检查后续字符,例如 uuu
.所以这是行不通的。通常使用正则表达式有点困难,因为您必须运行三个独立的正则表达式来检查每个字符,或者您必须指定这些字符之间的每个可能的顺序组合。
相反,请考虑在没有正则表达式的情况下解决此问题。以下解决方案非常简单,通过最多遍历一次来检查每个字符串:
List<string> words = new List<string> { "in", "inside", "on", "octopus", "commotion" };
var result = words.Where(x =>
{
var maxCounts = new Dictionary<char, int>{ { 'i', 1 }, { 'o', 2 }, { 'u', 3 } };
foreach (char c in x)
{
if (maxCounts.ContainsKey(c))
{
maxCounts[c]--;
if (maxCounts[c] < 0)
return false;
}
}
return true;
}).ToArray();
可以使用具有 3 个|
交替的简单正则表达式。
用于匹配输入是单个单词。
i.*?i|o(?:.*?o){2}|u(?:.*?u){3}
或者用于匹配文本中的单词。
'b(?:(?>'w*?i){2}|(?>'w*?o){3}|(?>'w*?u){4})'w*
-
'b
匹配单词边界 -
(?:
打开非捕获组 -
(?>
打开原子组 -
'w
匹配单词字符
在正则表达式中查看演示