#!/usr/bin/env python

class Group(object):
    def __init__(self, tup = []):
        self.tup = tup
        
    def add(self, chunks):
        pass
        
    def done(self):
        pass

class SortedInputGrouper(object):
    def __init__(self, infile, group_cols=[0]):
        self.infile = infile
        self.group_cols = group_cols
        self.tup = None
        self.chunks = None

    def group(self):
        try:
            self.chunks = self.infile.next()
        except StopIteration:
            return
        self.tup = [self.chunks[g] for g in self.group_cols]
        while self.tup != None:
            yield self._gather()
                
    def _gather(self):
        # Yield the capture chunks
        yield self.chunks
        # Look for more matching the tuple
        for chunks in self.infile:
            self.chunks = chunks
            ntup = [self.chunks[g] for g in self.group_cols]
            if ntup == self.tup:
                yield self.chunks
            else:
                self.tup = ntup
                return
        self.tup = None
    
class UnsortedInputGrouper(object):
    def __init__(self, infile, group_cls=Group, group_cols=[0]):
        self.infile = infile
        self.group_cols = group_cols
        self.dict = {}
        self.group_cls = group_cls

    def group(self):
        for chunks in self.infile:
            tup = [chunks[g] for g in self.group_cols]
            key = tuple(tup)
            if key not in self.dict:
                self.dict[key] = self.group_cls(tup)
            self.dict[key].add(chunks)
        for value in self.dict.itervalues():
            value.done()
            
def run_grouping(infile, group_cls=Group, group_cols=[0], ordered=False):
    group_cols = infile.header.indexes(group_cols)
    if ordered:
        grouper = SortedInputGrouper(infile, group_cols)
        for chunk in grouper.group():
            g = group_cls(grouper.tup)
            for item in chunk:
                g.add(item)
            g.done()
    else:
        UnsortedInputGrouper(infile, group_cls, group_cols).group()



@@ -1321,32 +1321,53 @@
 ef group(self):%0A
+        ordered = %5B%5D%0A
         for chun
@@ -1555,24 +1555,71 @@
 up_cls(tup)%0A
+                ordered.append(self.dict%5Bkey%5D)%0A
             
@@ -1670,30 +1670,15 @@
  in 
-self.dict.itervalues()
+ordered
 :%0A  
@@ -2146,10 +2146,8 @@
 group()%0A
-%0A%0A

maintain order in grouper