Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.5k views
in Technique[技术] by (71.8m points)

Number divided by 4 by python regex

I need to write code in python's regexes that will pass with strings representing numbers that are divisible by 4. Every number that has last two numbers that are divisable by 4 is divisable by 4 (0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96): So I have written some code:

import re
r = re.compile('^([048]$)|([-]{0,1}[0-9]*([12]|[16]|[20]|[24]|[28]|[32]|[36]|[40]|[44]|[48]|[52]|[56]|[60]|[64]|[68]|[72]|[76]|[80]|[84]|[88]|[92]|[96])$)')
m = r.search("32") # this is oke
m.group() # this is giving a wanted result
m = r.search("33") # here somthing is not right
m.group() # it shouldn't return 33 but it does

Why does my code is not working as I wish to? Why does it accept 33?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You are misunderstanding what [...] does. They are character classes; if 1 character in that class matches, the text matches:

>>> import re
>>> re.search(r'[32]', '3')
<_sre.SRE_Match object; span=(0, 1), match='3'>
>>> re.search(r'[32]', '2')
<_sre.SRE_Match object; span=(0, 1), match='2'>

Don't use a character class when you only want to match literal text.

The following would only match your specific 2-digit patterns:

r = re.compile('^([048]$)|(-?[0-9]*(12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)$)')

This works as expected:

>>> r = re.compile('^([048]$)|(-?[0-9]*(12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)$)')
>>> r.search("32")
<_sre.SRE_Match object; span=(0, 2), match='32'>
>>> r.search("33")
>>> r.search("33") is None
True

You are not matching numbers ending in 00 however (like 100, 200, etc.), which are also divisible by 4.

Note that the expression can be reduced further; the digits 0, 4 and 8 only follow even numbers while the digits 2 and 6 always follow odd numbers:

r = re.compile('^-?(?:[048]|[0-9]*(?:[02468][048]|[13579][26]))$')

I moved the - sign check out to apply to all numbers.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...