繁体   English   中英

正则表达式字符串仅包含允许的字符,并限制字符的出现

[英]Regex A string only contains allowed characters and limit the occurances of characters

这是我的角色出现限制。

Dictionary<string,int> chracterLimit=new  Dictionary<string,int>{{"c",1,"a",2}};

这是我的输入字符串...

var mystring="caac";

在这里,我检查LINQ是否对该字符有效,并且使用的字符数超过允许的限制。

bool checkstringvalid=!mystring
  .ToCharArray()
  .Select(c => c.ToString())
  .GroupBy(g => g)
  .ToList()
  .ToDictionary(
     d => d.FirstOrDefault(), 
     d => d.Count())
  .Any(z => z.Value > chracterGroup[z.Key]);

以上条件的输出为>这是无效的字符串。 因为c的出现为2,但允许的限制仅为1。

当我使用此功能时,要花费大量时间处理批量数据...而我的问题是,如何才能更轻松地检查此数据?

您能给我一个解决方案,以通过正则表达式对其进行检查吗? 我的想象像/ a {0,2} / / c {0,1} /

提前致谢!:)

LINQ引擎非常智能,因此您不太可能从当前的性能中获得很大的性能提升。 您可以做的一件事就是减少不必要的操作。 您所拥有的东西的更干净的版本是:

int s;
bool violation = myString.GroupBy(c => c.ToString())
                         .Any(g => characterLimit.TryGetValue(g.Key, out s) && s < g.Count());

这消除了从字符串到字符数组,列表到字典的转换。

对于比这更快的任何事情,您都需要放弃LINQ并采用迭代方法。

当使用符号工作时,让我们使用字符而不是字符串 (我们不希望使用过多的ToString() ,不是吗?):

   Dictionary<char, int> chracterLimit = new  Dictionary<char,int>{
     {'c', 1},
     {'a', 2}
   };

然后让我们尽早发现计数器示例,即,如果我们有"aaaaaaaaa....aaa"我们只需要读取 3 a ,而不是整个字符串:

   Dictionary<char, int> actual = new Dictionary<char, int>();

   bool checkStringValid = true;

   foreach (char c in mystring) {
     int count = 0;

     if (actual.TryGetValue(c, out count))
       actual[c] = ++count;  
     else
       actual.Add(c, ++count);

     if (chracterLimit.TryGetValue(c, out var limit)) {
       if (count > limit) {
         checkStringValid = false; // limit exceeded

         break;   
       } 
     }
     else {
       checkStringValid = false;  // invalid charcater detected

       break;   
     } 
   }  

上面的代码是对速度的优化; 如果您仅在寻找更具可读性的解决方案:

  bool checkstringvalid = !mystring
    .GroupBy(c => c)
    .Any(chunk => chracterLimit.TryGetValue(chunk.Key, out var limit)
       ? chunk.Skip(limit).Any()
       : true);

您的LINQ表达式具有很多转换。

怎么样呢?

 bool IsStringCompliant (string str, Dictionary<char><int> limits) 
 {
     var lim = new Dictionary<char><int>(limits);  // copy dict, allows re-use
     foreach (var c in str) {
       if (lim.ContainsKey(c)) {
           lim[c] -= 1;
           if (lim[c] <= 0) return false;
       }
       else return <<whatever result you want when a char is not in dict>>
    }
    return true;
 }

然后执行此操作以使用该功能。

   var characterLimit = new  Dictionary<string,int>{{'c',1,'a',2}};
   var mystring="caac";
   bool checkstringvalid = IsStringCompliant(mystring, characterLimit);

由于某些原因,这将很快。

  1. 它尽可能使用char而不是长度为1的string变量。
  2. 它发挥了C#编译器的循环优化技术的作用。
  3. 一旦知道字符串有效性失败,它将立即停止搜索。

另外,对于下一个程序员而言,它更容易理解。

我不知道您为什么要在这里使用正则表达式解决方案。 绝对,我不会更快。 可以说,如果超出简单示例的范围,它甚至会变得更加复杂和复杂。

仅出于演示目的,这是将您的原始条件转换为正则表达式:

  • 最多允许一个c
  • 最多允许两个a
^(?![^c\n]*c[^c\n]*c)(?![^a\n]*a[^a\n]*a[^a\n]*a).*$

演示

这里的想法是断言一个紫罗兰的规则,上面的规则:两个c或三个a使用否定的前瞻性以及修改后的否定字符类. 还有其他方法可以做到这一点。 您应该已经确信不要将正则表达式用于此任务。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM