Source code for tocoli.sort

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from tocoli.fn import first_kwarg

ASCENDING = False
DESCENDING = True

[docs]def sort_dict_by_key(d, reverse=False): """Returns a 'list' of tuple(key, value).""" from collections import OrderedDict from tocoli import PY2 def key(t): return t[0] if PY2: return sorted(OrderedDict(d).iteritems(), key=key, reverse=reverse) else: return sorted(OrderedDict(d).items(), key=key, reverse=reverse)
[docs]def sort_dict_by_value(d, reverse=False): """Returns a 'list' of tuple(key, value).""" from collections import OrderedDict from tocoli import PY2 def value(t): return t[1] if PY2: return sorted(OrderedDict(d).iteritems(), key=value, reverse=reverse) else: return sorted(OrderedDict(d).items(), key=value, reverse=reverse)
[docs]def sort_dicts_by_value(iterable, keys, values=first_kwarg, default=None, sequentially=True, reverse=False): """Sort a list of dictionaries as you like! Sort a 'list' of 'dict' by value. For simple sorting define `keys` as 'list' of 'str', where the strings are keynames. The functional `values` parameter behaves like the functional `key` parameter from the built-in `sorted` function. Examples: Simple sort by a key: >>> dicts = [{'name': 'Eve'}, {'name': 'Alice', 'email': 'alice@example.com'}, {'email': 'bob@example.com', 'name': 'Bob'}] >>> sort_dicts_by_value(dicts, ['name']) [{'name': 'Alice', 'email': 'alice@example.com'}, {'email': 'bob@example.com', 'name': 'Bob'}, {'name': 'Eve'}] Advanced sort for multiple keys and custom ``values`` function: >>> dicts = [{'price': 100}, {'price': 50, 'shipping': 40}, {'shipping': 5, 'price': 55}] >>> def total(price, shipping): return price + shipping >>> sort_dicts_by_value(dicts, ['price', 'shipping'], values=total, default=0, sequentially=False) [{'price': 55, 'shipping': 5}, {'price': 50, 'shipping': 40}, {'price': 100}] Sort dictionaries with non string keys: >>> dicts = [{1: False}, {'right': True, 1: False}, {1: True, 'right': True}] >>> def both(left, right): return left and right >>> sort_dicts_by_value(dicts, [{'key': 1, 'alias': 'left'}, 'right'], values=both, default=False, sequentially=False, reverse=True) [{1: True, 'right': True}, {1: False}, {1: False, 'right': True}] Args: iterable (list(dict)): The input dictonaries. keys (list(string or dict)): Sort by defined keys. If you have non string keys then `keys` should be a 'dict' instead of a 'list' with plain keys, which defines an alternative keyname for the non string key (e.g. ``keys={'key': 1: alias: 'one'}`` instead of ``keys=[1]``). **Note:** Those dictionaries which do not contain any key of `keys` will be removed from the result. Options: - ``'key'``: defines the key - ``'alias'``: alternative keyname for non string key names - ``'sort'``: sort order (``ASCENDING`` or ``DESCENDING``) values (function(**kwargs) -> value): Returns the value to sort by. Defaults to the first value of given keywords (unordered). The `values` function receives the defined keys as ``**kwargs``. Thus it is possible to process the values easily by their name (e.g. ``lambda firstname, lastname: firstname + ' ' + lastname``). **Note:** Take the `default` and the `sequentially` parameter into account, when you specify a custom `values` function. In sequential mode you have to expect different keywords (e.g. ``lambda **kwargs: …``). default (value): Default value. Defaults to ``None``. Defines the default value which is passed to the ``values`` function if a specified key from ``keys`` is not present or ``None``. sequentially (bool): Run in sequence. Defaults to True. If ``True`` each key in ``keys`` gets sorted one after the other else runs in batch mode and passes all ``keys`` to the ``values`` function. **Note:** The keys get sorted in reverse order. Thus the first key gets sorted as last and vice versa. reverse (bool): Reverse sorting. Defaults to False. Reverses sotring order for each key of `keys` idependently if the `sequentially` parameter is ``True`` else reverses the sorted 'list' as whole. Returns: list: A 'list' of 'dict'. **Note:** Those dictionaries which do not contain any key of `keys` will be removed from the result. """ from collections import OrderedDict def where(d): return any( k['key'] in d if isinstance(k, dict) else k in d for k in keys) def key(d): return values(**OrderedDict(( (k['alias'] if 'alias' in k else k['key'], default) if not k['key'] in d or d[k['key']] is None else (k['alias'] if 'alias' in k else k['key'], d[k['key']]) ) if isinstance(k, dict) else ( (k, default) if not k in d or d[k] is None else (k, d[k]) ) for k in keys)) if sequentially: for k in reversed(keys): if isinstance(k, dict) and 'sort' in k: if reverse: iterable = sort_dicts_by_value( iterable, [k], values, default, False, not k['sort']) else: iterable = sort_dicts_by_value( iterable, [k], values, default, False, k['sort']) else: iterable = sort_dicts_by_value( iterable, [k], values, default, False, reverse) return iterable else: return sorted((d for d in filter(where, iterable)), key=key, reverse=reverse)
[docs]def sort_dicts_by_similarity(iterable, keyword, keys, values=first_kwarg, default=None, sequentially=True, reverse=False, weights=(1, 1), case_sensitive=False): """Returns a sorted 'list' of 'dict'.""" from tocoli.ratio import similarity as sim def similarity(**kwargs): return sim(values(**kwargs), keyword, weights, case_sensitive) return sort_dicts_by_value(iterable, keys, similarity, default, sequentially, not reverse)
[docs]def sort_strings_by_similarity(iterable, keyword, reverse=False, weights=(1,1), case_sensitive=False): """Returns a sorted 'list'.""" from tocoli.ratio import similarity as sim def similarity(value): return sim(value, keyword, weights, case_sensitive) return sorted(iterable, key=similarity, reverse=reverse)
[docs]def sort_string(s, key=None, reverse=False): """Returns a string.""" return u''.join(sorted(s, key=key, reverse=reverse))
[docs]def sort_bytes(b, key=None, reverse=False, encoding='utf-8'): """Returns bytes.""" from tocoli.enc import encode return encode(u''.join(sorted(b, key=key, reverse=reverse)), encoding)
[docs]def sort_iter(i, key=None, reverse=False): """Returns a list.""" return sorted(i, key=key, reverse=reverse)
[docs]def sort_list(l, key=None, reverse=False): """Returns a list.""" return sorted(l, key=key, reverse=reverse)
[docs]def sort_tuple(t, key=None, reverse=False): """Returns a list.""" return sorted(t, key=key, reverse=reverse)
[docs]def sort_set(s, key=None, reverse=False): """Returns a list.""" return sorted(s, key=key, reverse=reverse)