Skip to content

Commit 57479ff

Browse files
committed
Merge pull request voronind#2 from mbayadinov/master
Fixed excessive pattern and enhanced to support negative ranges
2 parents 3492682 + 8512b90 commit 57479ff

File tree

2 files changed

+50
-5
lines changed

2 files changed

+50
-5
lines changed

range_regex/range_regex.py

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import math
2+
13
# coding=utf8
24

35
# Split range to ranges that has its unique pattern.
@@ -19,14 +21,38 @@ def regex_for_range(min_, max_):
1921
> regex_for_range(12, 345)
2022
'1[2-9]|[2-9]\d|[1-2]\d{2}|3[0-3]\d|34[0-5]'
2123
"""
24+
positive_subpatterns = []
25+
negative_subpatterns = []
26+
27+
if min_ < 0:
28+
min__ = 1
29+
if max_ < 0:
30+
min__ = abs(max_)
31+
max__ = abs(min_)
32+
33+
negative_subpatterns = split_to_patterns(min__, max__)
34+
min_ = 0
35+
36+
if max_ >= 0:
37+
positive_subpatterns = split_to_patterns(min_, max_)
38+
39+
negative_only_subpatterns = ['-' + val for val in negative_subpatterns if val not in positive_subpatterns]
40+
positive_only_subpatterns = [val for val in positive_subpatterns if val not in negative_subpatterns]
41+
intersected_subpatterns = ['-?' + val for val in negative_subpatterns if val in positive_subpatterns]
42+
43+
subpatterns = negative_only_subpatterns + intersected_subpatterns + positive_only_subpatterns
44+
return '|'.join(subpatterns)
45+
46+
47+
def split_to_patterns(min_, max_):
2248
subpatterns = []
2349

2450
start = min_
2551
for stop in split_to_ranges(min_, max_):
2652
subpatterns.append(range_to_pattern(start, stop))
2753
start = stop + 1
2854

29-
return '|'.join(subpatterns)
55+
return subpatterns
3056

3157

3258
def split_to_ranges(min_, max_):
@@ -41,12 +67,12 @@ def split_to_ranges(min_, max_):
4167
stop = fill_by_nines(min_, nines_count)
4268

4369
zeros_count = 1
44-
stop = fill_by_zeros(max_, zeros_count) - 1
45-
while min_ < stop < max_:
70+
stop = fill_by_zeros(max_ + 1, zeros_count) - 1
71+
while min_ < stop <= max_:
4672
stops.add(stop)
4773

4874
zeros_count += 1
49-
stop = fill_by_zeros(max_, zeros_count) - 1
75+
stop = fill_by_zeros(max_ + 1, zeros_count) - 1
5076

5177
stops = list(stops)
5278
stops.sort()

range_regex/tests.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,28 @@ def _verify_range(self, regex, min_, max_, from_min_, to_max_):
1212

1313
def test_quality(self):
1414
self.assertEqual(regex_for_range(1, 1), '1')
15+
self.assertEqual(regex_for_range(0, 1), '[0-1]')
16+
self.assertEqual(regex_for_range(-1, -1), '-1')
17+
self.assertEqual(regex_for_range(-1, 0), '-1|0')
18+
self.assertEqual(regex_for_range(-1, 1), '-1|[0-1]')
19+
self.assertEqual(regex_for_range(-4, -2), '-[2-4]')
20+
self.assertEqual(regex_for_range(-3, 1), '-[1-3]|[0-1]')
21+
self.assertEqual(regex_for_range(-2, 0), '-[1-2]|0')
22+
self.assertEqual(regex_for_range(0, 2), '[0-2]')
23+
self.assertEqual(regex_for_range(-1, 3), '-1|[0-3]')
1524
self.assertEqual(regex_for_range(65666, 65667), '6566[6-7]')
1625
self.assertEqual(regex_for_range(12, 3456), r'1[2-9]|[2-9]\d|[1-9]\d{2}|[1-2]\d{3}|3[0-3]\d{2}|34[0-4]\d|345[0-6]')
17-
26+
self.assertEqual(regex_for_range(1, 19), r'[1-9]|1\d')
27+
self.assertEqual(regex_for_range(1, 99), r'[1-9]|[1-9]\d')
28+
29+
def test_optimization(self):
30+
self.assertEqual(regex_for_range(-9, 9), r'-[1-9]|\d')
31+
self.assertEqual(regex_for_range(-19, 19), r'-[1-9]|-?1\d|\d')
32+
self.assertEqual(regex_for_range(-29, 29), r'-[1-9]|-?[1-2]\d|\d')
33+
self.assertEqual(regex_for_range(-99, 99), r'-[1-9]|-?[1-9]\d|\d')
34+
self.assertEqual(regex_for_range(-999, 999), r'-[1-9]|-?[1-9]\d|-?[1-9]\d{2}|\d')
35+
self.assertEqual(regex_for_range(-9999, 9999), r'-[1-9]|-?[1-9]\d|-?[1-9]\d{2}|-?[1-9]\d{3}|\d')
36+
1837
def test_equal(self):
1938
regex = bounded_regex_for_range(1, 1)
2039
self._verify_range(regex, 1, 1, 0, 100)

0 commit comments

Comments
 (0)