8000 Adds groupsof built-in by kbaskett248 · Pull Request #309 · evhub/coconut · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Adds groupsof built-in #309

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Aug 29, 2017
24 changes: 24 additions & 0 deletions DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1658,6 +1658,30 @@ import itertools
positives = itertools.dropwhile(numiter, lambda x: x<0)
```

### `groupsof`

Coconut provides the `groupsof` built-in to iterate over fixed-length groups of items from an iterable. For example, `groupsof(2, range(1, 11))` returns an iterator that will return the integers 1 - 10 in pairs as tuples.

##### Example

**Coconut:**
```coconut
pairs = groupsof(2, numiter)
```

**Python:**
```coconut_python
pairs = []
group = []
for item in numiter:
group.append(item)
if len(group) == 2:
pairs.append(tuple(group))
group = []
if group:
pairs.append(tuple(group))
```

### `tee`

Coconut provides an optimized version of `itertools.tee` as a built-in under the name `tee`.
Expand Down
36 changes: 36 additions & 0 deletions coconut/compiler/templates/header.py_template
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,42 @@ class count{object}:
return isinstance(other, self.__class__) and self.start == other.start and self.step == other.step
def __fmap__(self, func):
return _coconut_map(func, self)
class groupsof{object}:
"""groupsof(n, iterable) returns an iterator that returns groups of length n.
If the length of the iterable is not divisible by n, the last group may be of size < n.
"""
__slots__ = ("_grp_size", "_iter")
def __init__(self, n, iterable):
self._iter = iterable
try:
self._grp_size = int(n)
except ValueError:
raise TypeError("group size must be an int: %s" % (n, ))
if self._grp_size <= 0:
raise ValueError("group size (%s) must be positive" % (self._grp_size, ))
def __iter__(self):
loop = True
iterator = iter(self._iter)
while loop:
group = []
for _ in range(0, self._grp_size):
try:
group.append(next(iterator))
except StopIteration:
loop = False
break
if group:
yield tuple(group)
def __len__(self):
return _coconut.len(self._iter)
def __repr__(self):
return "groupsof(%r)" % (_coconut.repr(self._iter), )
def __reduce__(self):
return (self.__class__, (self._grp_size, self._iter))
def __copy__(self):
return self.__class__(self._grp_size, _coconut.copy.copy(self._iter))
def __fmap__(self, func):
return _coconut_map(func, self)
def recursive_iterator(func):
"""Decorator that optimizes a function for iterator recursion."""
tee_store, backup_tee_store = {empty_dict}, []
Expand Down
18 changes: 18 additions & 0 deletions tests/src/cocotest/agnostic/main.coco
935B
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,15 @@ def main_test():
assert (range10 |> reversed).count(10) == 0
assert (range10 |> reversed).index(3)

assert range(1,11) |> groupsof$(1) |> list == [(1,),(2,),(3,),(4,),(5,),(6,),(7,),(8,),(9,),(10,)]
assert range(1,11) |> groupsof$(2) |> list == [(1,2),(3,4),(5,6),(7,8),(9,10)]
assert range(1,11) |> groupsof$(2.5) |> list == [(1,2),(3,4),(5,6),(7,8),(9,10)]
assert range(1,11) |> groupsof$(3) |> list == [(1,2,3),(4,5,6),(7,8,9),(10,)]
assert range(1,11) |> groupsof$(4) |> list == [(1,2,3,4),(5,6,7,8),(9,10)]
assert_raises(() -> range(1,11) |> groupsof$("A"), TypeError)
assert_raises(() -> range(1,11) |> groupsof$(0), ValueError)
assert_raises(() -> range(1,11) |> groupsof$(-1), ValueError)

assert range(1, 3) |> enumerate |> list == [(0, 1), (1, 2)]
assert range(2) |> enumerate$(start=1) |> list == [(1, 0), (2, 1)]
assert range(10) |> enumerate |> len == 10
Expand Down Expand Up @@ -428,6 +437,15 @@ def main_test():

def tco_func() = tco_func()

def assert_raises(c, exc):
"""Test whether callable c raises an exception of type exc."""
try:
c()
except exc:
return True
else:
raise AssertionError("%s failed to raise %s exception" % (c, exc))

def main(*args):
"""Asserts arguments and executes tests."""
assert all(args)
Expand Down
0