Skip to content

Commit 335d773

Browse files
author
Zheyuan Chen
authored
Merge pull request #7 from terciodemelo/adds-steps-to-ranges
Adds steps to ranges
2 parents 186d2c1 + 988c3c2 commit 335d773

File tree

3 files changed

+65
-3
lines changed

3 files changed

+65
-3
lines changed

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,16 +79,29 @@ pipe(['google', 'twitter', 'yahoo', 'facebook', 'github'])
7979
# similar to `range(1, 11)`, but this is an iterator.
8080
# Python's nasty range() is right-exclusive. This is right-inclusive.
8181

82+
1 /to/ 10 /by/ 2
83+
# similar to `range(1, 11, 2)`, you can also specify step size
84+
8285
10 /to/ 1
8386
# similar to `range(10, 0, -1)`, you can also use decreasing ranges
8487

88+
10 /to/ 1 /by/ 2
89+
# similar to `range(10, 0, -2)`, you can also specify negative step size
90+
8591
'0' /to/ '9'
8692
# similar to '0123456789', but this is an iterator.
8793
# we can also have a range of characters :)
8894

95+
'A' /to/ 'Z' /by/ 3
96+
# similar to 'ADGJMPSVY', but this is an iterator. Steps also work for characters!
97+
8998
'v' /to/ 'd'
9099
# similar to 'vutsrqponmlkjihgfed', but this is an iterator
91100
# e can also have *decreasing* range of characters :)
101+
102+
'v' /to/ 'd' /by/ 3
103+
# similar to 'vspmjgd', but this is an iterator
104+
# e can also have *decreasing* range of characters with negative steps
92105
```
93106

94107
`/to/` has some advanced features

syntax_sugar/infix.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,26 @@ def __init__(self, start, end):
3939

4040
self.start = start
4141
self.curr = self.start
42-
self.step = 1 if end > start else -1
42+
self._step = 1 if end > start else -1
4343
self.end = end
4444

45+
@property
46+
def step(self):
47+
return self._step
48+
49+
@step.setter
50+
def step(self, value):
51+
if value == 0 or not value /is_a/ int:
52+
raise TypeError('Interval must be an integer different from 0')
53+
self._step = value
54+
4555
def __mul__(self, rhs):
4656
return product(self, rhs)
4757

4858
def __iter__(self):
4959
return self
5060

5161
def __next__(self):
52-
if self.step == 0 or not self.step /is_a/ int:
53-
raise TypeError('Interval must be an integer different from 0')
5462
def next_number():
5563
too_big = self.step > 0 and self.curr > self.end
5664
too_small = self.step < 0 and self.curr < self.end
@@ -90,6 +98,18 @@ def __str__(self):
9098
def to(start, end):
9199
return To(start, end)
92100

101+
@infix
102+
def by(to_object, step):
103+
if to_object.end >= to_object.start and step < 0:
104+
to_object.step = -step
105+
elif to_object.end <= to_object.start and step > 0:
106+
to_object.step = -step
107+
else:
108+
to_object.step = step
109+
110+
return to_object
111+
112+
93113
__all__ = [
94114
'infix',
95115
'of',
@@ -98,6 +118,7 @@ def to(start, end):
98118
'pair',
99119
'join',
100120
'to',
121+
'by',
101122
'INF',
102123
'hasattr',
103124
'fmap',

tests/test_infix.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,18 @@ def test_int_to_int():
1010
start, end = end, start
1111
assert list(start /to/ end) == list(range(start, end - 1, -1))
1212

13+
def test_int_to_int_with_step():
14+
for i in range(100):
15+
start, end = random.randint(1, 1e3), random.randint(1, 1e3)
16+
step = random.randint(1, 10)
17+
end += start
18+
assert list(start /to/ end /by/ step) == list(range(start, end + 1, step))
19+
assert list(start /to/ end /by/ -step) == list(range(start, end + 1, step))
20+
21+
start, end = end, start
22+
assert list(start /to/ end /by/ -step) == list(range(start, end - 1, -step))
23+
assert list(start /to/ end /by/ step) == list(range(start, end - 1, -step))
24+
1325
def test_str_to_str():
1426
assert str('A' /to/ 'Z') == 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
1527
assert str('Z' /to/ 'A') == 'ZYXWVUTSRQPONMLKJIHGFEDCBA'
@@ -19,6 +31,22 @@ def test_str_to_str():
1931
assert str('V' /to/ 'D') == 'VUTSRQPONMLKJIHGFED'
2032
assert str('v' /to/ 'd') == 'vutsrqponmlkjihgfed'
2133

34+
def test_str_to_str_with_step():
35+
assert str('A' /to/ 'Z' /by/ 3) == 'ADGJMPSVY'
36+
assert str('A' /to/ 'Z' /by/ -3) == 'ADGJMPSVY'
37+
assert str('Z' /to/ 'A' /by/ -3) == 'ZWTQNKHEB'
38+
assert str('Z' /to/ 'A' /by/ 3) == 'ZWTQNKHEB'
39+
assert str('a' /to/ 'z' /by/ 4) == 'aeimquy'
40+
assert str('a' /to/ 'z' /by/ -4) == 'aeimquy'
41+
assert str('z' /to/ 'a' /by/ -4) == 'zvrnjfb'
42+
assert str('z' /to/ 'a' /by/ 4) == 'zvrnjfb'
43+
assert str('D' /to/ 'V' /by/ 5) == 'DINS'
44+
assert str('D' /to/ 'V' /by/ -5) == 'DINS'
45+
assert str('V' /to/ 'D' /by/ -5) == 'VQLG'
46+
assert str('V' /to/ 'D' /by/ 5) == 'VQLG'
47+
assert str('v' /to/ 'd' /by/ -3) == 'vspmjgd'
48+
assert str('v' /to/ 'd' /by/ 3) == 'vspmjgd'
49+
2250
def test_take():
2351
assert 1 /to/ INF /take/ 5 == [1,2,3,4,5]
2452

0 commit comments

Comments
 (0)