'Does a `map` operation while displaying a progress bar with
percentage complete.
def work(i):
print(i)
ProgressBar.map(work, range(50))
Parameters
function : function
Function to call for each step
items : sequence
Sequence where each element is a tuple of arguments to pass to
*function*.
multiprocess : bool, optional
If `True`, use the `multiprocessing` module to distribute each
task to a different processor core.
ipython_widget : bool, optional
If `True`, the progress bar will display as an IPython
notebook widget.
file : writeable file-like object, optional
The file to write the progress bar to.  Defaults to
`sys.stdout`.  If ``file`` is not a tty (as determined by
calling its `isatty` member, if any), the scrollbar will
be completely silent.
step : int, optional
Update the progress bar at least every *step* steps (default: 100).
If ``multiprocess`` is `True`, this will affect the size
of the chunks of ``items`` that are submitted as separate tasks
to the process pool.  A large step size may make the job
complete faster if ``items`` is very long.'

@classmethod
def map(cls, function, items, multiprocess=False, file=None, step=100, ipython_widget=False):

    results = []
    if (file is None):
        file = _get_stdout()
    with cls(len(items), ipython_widget=ipython_widget, file=file) as bar:
        if bar._ipython_widget:
            chunksize = step
        else:
            default_step = max(int((float(len(items)) / bar._bar_length)), 1)
            chunksize = min(default_step, step)
        if (not multiprocess):
            for (i, item) in enumerate(items):
                results.append(function(item))
                if ((i % chunksize) == 0):
                    bar.update(i)
        else:
            p = multiprocessing.Pool()
            for (i, result) in enumerate(p.imap_unordered(function, items, chunksize=chunksize)):
                bar.update(i)
                results.append(result)
            p.close()
            p.join()
    return results
