Ho Yeung Lee wrote:

> from itertools import groupby
> 
> testing1 = [(1,1),(2,3),(2,4),(3,5),(3,6),(4,6)]
> def isneighborlocation(lo1, lo2):
>     if abs(lo1[0] - lo2[0]) == 1  or lo1[1] == lo2[1]:
>         return 1
>     elif abs(lo1[1] - lo2[1]) == 1  or lo1[0] == lo2[0]:
>         return 1
>     else:
>         return 0
> 
> groupda = groupby(testing1, isneighborlocation)
> for key, group1 in groupda:
>     print key
>     for thing in group1:
>         print thing
> 
> expect output 3 group
> group1 [(1,1)]
> group2 [(2,3),(2,4]
> group3 [(3,5),(3,6),(4,6)]

groupby() calculates the key value from the current item only, so there's no 
"natural" way to apply it to your problem.

Possible workarounds are to feed it pairs of neighbouring items (think 
zip()) or a stateful key function. Below is an example of the latter:

$ cat sequential_group_class.py
from itertools import groupby

missing = object()

class PairKey:
    def __init__(self, continued):
        self.prev = missing
        self.continued = continued
        self.key = False

    def __call__(self, item):
        if self.prev is not missing and not self.continued(self.prev, item):
            self.key = not self.key
        self.prev = item
        return self.key

def isneighborlocation(lo1, lo2):
    x1, y1 = lo1
    x2, y2 = lo2
    dx = x1 - x2
    dy = y1 - y2
    return dx*dx + dy*dy <= 1

items = [(1,1),(2,3),(2,4),(3,5),(3,6),(4,6)]

for key, group in groupby(items, key=PairKey(isneighborlocation)):
    print key, list(group)

$ python sequential_group_class.py 
False [(1, 1)]
True [(2, 3), (2, 4)]
False [(3, 5), (3, 6), (4, 6)]


-- 
https://mail.python.org/mailman/listinfo/python-list

Reply via email to