def partitionByFunc(origseq, partfunc):
    """Partitions a sequence into a number of sequences, based on the `partfunc`.
    Returns ``(allseqs, indices)``, where:
        - `allseqs` is a dictionary of output sequences, based on output values
          of `partfunc(el)`.
        - `indices` is a dictionary of ``(outval, i) -> orig_i``, which allows mapping results back.
    So if your `partfunc` returns 'foo' and 'bar', `allseqs` will have ``{'foo': [...], 'bar': [...]}``.
    You access `indices` using ``(partout, seq_i)``, where `partout` is 'foo' or 'bar' in this case, and
    `seq_i` is the index number from the ``allseqs[partout]`` sequence.

    This function is very useful for categorizing a list's entries based on some
    function. If your function was binary, you would normally do it using 2 list
    comprehensions::
        a = [el for el in seq if partfunc(el)]
        b = [el for el in seq if not partfunc(el)]

    But that quickly gets inefficient and bloated if you have more complicated
    partition functions, which is where this function becomes useful.
    """
    allseqs = {}
    indices = {}
    for i, el in enumerate(origseq):
        partout = partfunc(el)
        seq = allseqs.setdefault(partout, [])
        indices[(partout, len(seq))] = i
        seq.append(el)
    return allseqs, indices