'Constructor
@param items: ordered iterable of items (e.g. list, tuple,
iterator, Rows), grouping tries to maintain
the original item order
@param groupby: attribute key or ordered iterable of
attribute keys (e.g. list, tuple, iterator)
for the items to be grouped by; grouping
happens in order of appearance of the keys
@param aggregate: aggregates to compute, list of tuples
(method, key)
@param value: the grouping values for this group (internal)'

def __init__(self, items, groupby=None, aggregate=None, values=None):

    self._groups_dict = {}
    self._groups_list = []
    self.values = (values or {})
    self._aggregates = {}
    if groupby:
        if isinstance(groupby, basestring):
            groupby = [groupby]
        else:
            groupby = list(groupby)
        self.key = groupby.pop(0)
        self.groupby = groupby
        self.items = None
        for item in items:
            self.add(item)
    else:
        self.key = None
        self.groupby = None
        self.items = list(items)
    if aggregate:
        if (type(aggregate) is tuple):
            aggregate = [aggregate]
        for (method, key) in aggregate:
            self.aggregate(method, key)
