正在计数的正则表达式

问题描述:

我有0和1的字符串。 我想要一个正则表达式,使得0的数量少于1的数量。正在计数的正则表达式

例子:

0111 - match (there is 1x0 and 3x1 and 1 < 3) 
00011 - pattern fails (3x0 and 2x1 but 3<2 is false) 
0101010 - pattern fails (4x0 and 3x1 but 4<3 is false) 
+0

请指定正则表达式的风味。 – revo

+0

'我有'.......'我想'....... –

随着PCRE和Perl的可能,你可以使用递归模式做到这一点:

^((?:0(?1)??1|1(?1)??0)*+)(?:1(?1))+$ 

demo

细节:

^ 
(# group 1: matches balanced 0 and 1 
    (?: 
     0(?1)??1 # part that starts with 0 and ends with 1 
       # (?1) calls the group 1 subpattern itself (recursion) 
     | 
     1(?1)??0 # same thing for 1 ... 0 
    )*+ # repeat 
) 
(?: 
    1  
    (?1) 
)+ # ensure there's at least one 1 that isn't matched by (?1) 
$ 

使用.NET正则表达式引擎:

^(?>(?<c>0)|(?<-c>1))*(?(c)(?!$))(?:1(?>(?<c>0)|(?<-c>1))*(?(c)(?!$)))+$ 

demo

此时更直观:

(?<c>...)增加一个计数器c和(?<-c>...)减小相同的计数器。当计数器c不为零时,条件(?(c)(?!$))失败(?!$)是始终失败的子模式)

此模式的全局结构比前面所述一样:

^ (balanced parts)* (?: 1 (balanced parts)*)+ $ 

的其他可能的结构与PCRE是:

^ (?: balanced parts | (1))*+ (force to fail if capture group doesn't exist) $ 

PCRE:

^(?:((?:0(?1)?1|1(?1)?0)+)|(1))*+(?(2)|(*F))$ 
+0

正如我记得这个问题被指定为Peter Linz's * Formal Languages和Automata *书籍的一个练习部分。不过,我应该问,你是如何将这个想法作为强制性表达而不是在第一个捕获组中交替的? – revo

+0

@revo:'(?:1(?1))+'只是'1(?:1 |(?1))*'的改进形式(展开形式)。你也可以这样写:https://regex101.com/r/zE1Nqt/1 –

+0

1)当我用这种方式思考'S - > SS | 0S1 | 1S0 | 1S | 1'我不能了解你如何制定'1(?1)'强制性的。为什么它是强制性的? (我应该说语法的制作不会产生例如'w = 10110',所以如果你点亮的话我会很感激)2)我们应该怎么做才能避免使用粗糙零的字符串的CB:[**'111111111110000000000011101011010001111111 ** ](https://regex101.com/r/alpwgU/2)? – revo

正则表达式用于匹配的模式,但你似乎想计算字符数的情况。就我所知,这不是正则表达式。

你需要做的是创建一个数组或其他结构来保存你之后特定字符的计数器值。然后,您将迭代输入字符串,并根据手头的角色更新相应的计数器。

我认为你可以实现你的目标没有正则表达式。

FOREACH:

string s = "10101010011"; 
int zeros = 0; 
int ones = 0; 
foreach (char c in s) 
{ 
    if (c == '0') 
    { 
     zeros++; 
    } 
    else 
    { 
     ones++; 
    } 
} 
Console.WriteLine(zeros < ones); 
Console.ReadLine(); 

LINQ:

string s = "10101010011"; 
int zeros = s.Count(x => x == '0'); 
int ones = s.Count(x => x == '1'); 
Console.WriteLine(zeros < ones); 
Console.ReadLine(); 

既然你没有指定的语言。这是你如何在Python中实现它,而不使用正则表达式。您可以将此逻辑移植到您的语言。

a= """0111 
00011 
0101010""" 

a = a.split('\n') 
print a 

for b in a: 
    zeroes = list(b).count('0') 
    ones = list(b).count('1') 
    if zeroes < ones: 
     print b 

输出:

['0111', '00011', '0101010'] 
0111