簡體   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