Skip to content

Commit

Permalink
added take_while
Browse files Browse the repository at this point in the history
  • Loading branch information
WitoldFracek committed Nov 8, 2024
1 parent 8246a35 commit 748e923
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 13 deletions.
19 changes: 19 additions & 0 deletions src/qwlist/eager.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,5 +399,24 @@ def inner():
yield elem
return EagerQList(inner())

def take_while(self, pred: Callable[[T], bool]) -> "Lazy[T]":
"""
Creates a new EagerQList that contains elements based on a predicate. Takes a function as an argument.
It will call this function on each element of the iterator, and yield elements while the function
returns `True`. After `False` is returned, iteration stops, and the rest of the elements is ignored.
Args:
pred (Callable[[T], bool]): `function (T) -> bool`
Returns:
`EagerQList[T]`
"""
def inner():
for elem in self:
if not pred(elem):
return
yield elem
return EagerQList(inner())

if __name__ == '__main__':
EagerQList([[1, 2], 3]).flatten().foreach(print)
36 changes: 30 additions & 6 deletions src/qwlist/qwlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -492,8 +492,9 @@ def sum(self, init: Optional[T] = None) -> T:
def take_while(self, pred: Callable[[T], bool]) -> "Lazy[T]":
"""
Creates a new Lazy that yields elements based on a predicate. Takes a function as an argument.
Creates a new Lazy that yields elements based on a predicate. Takes a function as an argument.
It will call this function on each element of the iterator, and yield elements while the function
returns `True`. After `False` is returned, iteration stops, and the rest of the elements are ignored.
returns `True`. After `False` is returned, iteration stops, and the rest of the elements is ignored.
Args:
pred (Callable[[T], bool]): `function (T) -> bool`
Expand Down Expand Up @@ -1006,6 +1007,25 @@ def inner():
yield elem
return Lazy(inner())

def take_while(self, pred: Callable[[T], bool]) -> "Lazy[T]":
"""
Creates a Lazy that yields elements based on a predicate. Takes a function as an argument.
It will call this function on each element of the iterator, and yield elements while the function
returns `True`. After `False` is returned, iteration stops, and the rest of the elements is ignored.
Args:
pred (Callable[[T], bool]): `function (T) -> bool`
Returns:
`Lazy[T]`
"""
def inner():
for elem in self:
if not pred(elem):
return
yield elem
return Lazy(inner())


if __name__ == '__main__':
def naturals(start):
Expand All @@ -1014,10 +1034,14 @@ def naturals(start):
yield current
current += 1

for n in Lazy(naturals(0)).take(10):
print(n)

primes = Lazy(naturals(2)).filter(lambda n: Lazy(naturals(2)).take_while(lambda p: p * p <= n).all(lambda x: n % x != 0))
for p in primes.take(100).skip(80):
primes = (
Lazy(naturals(2))
.filter(lambda n: (
Lazy(naturals(2))
.take_while(lambda p: p * p <= n)
.all(lambda x: n % x != 0)
))
)
for p in primes.skip(1000).take(10):
print(p)

6 changes: 3 additions & 3 deletions src/todo.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
QList, Lazy, EagerQList
### take_while
[ ] [ ] [ ] implemented \
[ ] [ ] [ ] documented \
[ ] [ ] [ ] tested
[x] [x] [x] implemented \
[x] [x] [x] documented \
[x] [x] [x] tested

### all
[x] [x] [x] implemented \
Expand Down
21 changes: 20 additions & 1 deletion tests/test_eager.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ def test_all():
assert not EagerQList(['', 'a', 'aa']).all()
assert EagerQList(range(10)).filter(lambda x: x % 2 == 1).map(lambda x: x * 2).all(lambda x: x % 2 == 0)


def test_any():
assert EagerQList([1, True, [1, 2, 3]]).any()
assert not EagerQList().any()
Expand All @@ -313,4 +314,22 @@ def test_any():
assert EagerQList(['abc', 'def', 'gdi']).any(mapper=lambda s: len(s) > 1)
assert not EagerQList([False, False, False]).any()
assert EagerQList(['', 'a', 'aa']).any()
assert EagerQList(range(10)).filter(lambda x: x < 5).all(lambda x: x % 2 == 0)
assert EagerQList(range(10)).filter(lambda x: x < 5).any(lambda x: x % 2 == 0)


def test_take_while():
expected = EagerQList([0, 1, 2])
res = EagerQList(range(10)).take_while(lambda n: n < 3)
assert res == expected

expected = EagerQList()
res = EagerQList(range(10)).take_while(lambda n: isinstance(n, str))
assert res == expected

expected = EagerQList()
res = EagerQList([]).take_while(lambda x: x > 2)
assert res == expected

expected = EagerQList(range(10))
res = EagerQList(range(5)).take_while(lambda x: x < 100).chain([5, 6, 7, 8, 9])
assert res == expected
21 changes: 20 additions & 1 deletion tests/test_lazy.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,11 +374,30 @@ def test_all():
assert not Lazy([False, False, False]).all()
assert not Lazy(['', 'a', 'aa']).all()


def test_any():
assert Lazy([1, True, [1, 2, 3]]).any()
assert not Lazy([]).any()
assert Lazy([True, False, False]).any()
assert Lazy([True, True, False]).any(mapper=lambda x: not x)
assert Lazy(['abc', 'def', 'gdi']).any(mapper=lambda s: len(s) > 1)
assert not Lazy([False, False, False]).any()
assert Lazy(['', 'a', 'aa']).any()
assert Lazy(['', 'a', 'aa']).any()


def test_take_while():
expected = QList([0, 1, 2])
res = Lazy(range(10)).take_while(lambda n: n < 3).collect()
assert res == expected

expected = QList()
res = Lazy(range(10)).take_while(lambda n: isinstance(n, str)).collect()
assert res == expected

expected = QList()
res = Lazy([]).take_while(lambda x: x > 2).collect()
assert res == expected

expected = QList(range(10))
res = Lazy(range(5)).take_while(lambda x: x < 100).chain([5, 6, 7, 8, 9]).collect()
assert res == expected
23 changes: 21 additions & 2 deletions tests/test_qwlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ def test_flatten():
assert expected == res

try:
QList([1, 2, 3]).flatten()
QList([1, 2, 3]).flatten().collect()
except TypeError:
assert True
else:
Expand Down Expand Up @@ -413,6 +413,7 @@ def test_all():
assert not QList(['', 'a', 'aa']).all()
assert QList(range(10)).filter(lambda x: x % 2 == 1).map(lambda x: x * 2).all(lambda x: x % 2 == 0)


def test_any():
assert QList([1, True, [1, 2, 3]]).any()
assert not QList().any()
Expand All @@ -421,5 +422,23 @@ def test_any():
assert QList(['abc', 'def', 'gdi']).any(mapper=lambda s: len(s) > 1)
assert not QList([False, False, False]).any()
assert QList(['', 'a', 'aa']).any()
assert QList(range(10)).filter(lambda x: x < 5).all(lambda x: x % 2 == 0)
assert QList(range(10)).filter(lambda x: x < 5).any(lambda x: x % 2 == 0)


def test_take_while():
expected = QList([0, 1, 2])
res = QList(range(10)).take_while(lambda n: n < 3).collect()
assert res == expected

expected = QList()
res = QList(range(10)).take_while(lambda n: isinstance(n, str)).collect()
assert res == expected

expected = QList()
res = QList().take_while(lambda x: x > 2).collect()
assert res == expected

expected = QList(range(10))
res = QList(range(5)).take_while(lambda x: x < 100).chain([5, 6, 7, 8, 9]).collect()
assert res == expected

0 comments on commit 748e923

Please sign in to comment.