Takes a list of evaluation results `res` returned by a LDA evaluation function (a list in the form
    `[(parameter_set_1, {'<metric_name>': result_1, ...}), ..., (parameter_set_n, {'<metric_name>': result_n, ...})]`)
    and returns a list with tuple pairs using  only the parameter `param` from the parameter sets in the evaluation
    results such that the returned list is
    `[(param_1, {'<metric_name>': result_1, ...}), ..., (param_n, {'<metric_name>': result_n, ...})]`.
    Optionally order either by parameter value (`sort_by=None` - the default) or by result metric
    (`sort_by='<metric name>'`).

def results_by_parameter(res, param, sort_by=None, sort_desc=False):
    """
    Takes a list of evaluation results `res` returned by a LDA evaluation function (a list in the form
    `[(parameter_set_1, {'<metric_name>': result_1, ...}), ..., (parameter_set_n, {'<metric_name>': result_n, ...})]`)
    and returns a list with tuple pairs using  only the parameter `param` from the parameter sets in the evaluation
    results such that the returned list is
    `[(param_1, {'<metric_name>': result_1, ...}), ..., (param_n, {'<metric_name>': result_n, ...})]`.
    Optionally order either by parameter value (`sort_by=None` - the default) or by result metric
    (`sort_by='<metric name>'`).
    """
    if len(res) == 0:
        return []

    tuples = [(p[param], r) for p, r in res]

   # single validation results
    if len(tuples[0]) != 2:
        raise ValueError('invalid evaluation results passed')

    params, metric_results = list(zip(*tuples))
    if sort_by:
        sorted_ind = argsort([r[sort_by] for r in metric_results])
    else:
        sorted_ind = argsort(params)

    if sort_desc:
        sorted_ind = reversed(sorted_ind)

    measurements = tuples

    return [measurements[i] for i in sorted_ind]