def pluck(collection, path): """Retrieves the value of a specified property from all elements in the collection. Args: collection (list): List of dicts. path (str|list): Collection's path to pluck Returns: list: Plucked list. Example: >>> pluck([{'a': 1, 'b': 2}, {'a': 3, 'b': 4}, {'a': 5, 'b': 6}], 'a') [1, 3, 5] >>> pluck([[[0, 1]], [[2, 3]], [[4, 5]]], '0.1') [1, 3, 5] >>> pluck([{'a': {'b': 1}}, {'a': {'b': 2}}], 'a.b') [1, 2] >>> pluck([{'a': {'b': [0, 1]}}, {'a': {'b': [2, 3]}}], 'a.b.1') [1, 3] >>> pluck([{'a': {'b': [0, 1]}}, {'a': {'b': [2, 3]}}], ['a', 'b', 1]) [1, 3] .. versionadded:: 1.0.0 .. versionchanged:: 4.0.0 Function removed. .. versionchanged:: 4.0.1 Made property access deep. """ return map_(collection, pyd.property_(path))
def properties(*paths): """Like :func:`property_` except that it returns a list of values at each path in `paths`. Args: *path (str|list): Path values to fetch from object. Returns: function: Function that returns object's path value. Example: >>> getter = properties('a', 'b', ['c', 'd', 'e']) >>> getter({'a': 1, 'b': 2, 'c': {'d': {'e': 3}}}) [1, 2, 3] .. versionadded:: 4.1.0 """ return lambda obj: [getter(obj) for getter in (pyd.property_(path) for path in paths)]
def order_by(collection, keys, orders=None, reverse=False): """This method is like :func:`sort_by` except that it sorts by key names instead of an iteratee function. Keys can be sorted in descending order by prepending a ``"-"`` to the key name (e.g. ``"name"`` would become ``"-name"``) or by passing a list of boolean sort options via `orders` where ``True`` is ascending and ``False`` is descending. Args: collection (list|dict): Collection to iterate over. keys (list): List of keys to sort by. By default, keys will be sorted in ascending order. To sort a key in descending order, prepend a ``"-"`` to the key name. For example, to sort the key value for ``"name"`` in descending order, use ``"-name"``. orders (list, optional): List of boolean sort orders to apply for each key. ``True`` corresponds to ascending order while ``False`` is descending. Defaults to ``None``. reverse (bool, optional): Whether to reverse the sort. Defaults to ``False``. Returns: list: Sorted list. Example: >>> items = [{'a': 2, 'b': 1}, {'a': 3, 'b': 2}, {'a': 1, 'b': 3}] >>> results = order_by(items, ['b', 'a']) >>> assert results == [{'a': 2, 'b': 1},\ {'a': 3, 'b': 2},\ {'a': 1, 'b': 3}] >>> results = order_by(items, ['a', 'b']) >>> assert results == [{'a': 1, 'b': 3},\ {'a': 2, 'b': 1},\ {'a': 3, 'b': 2}] >>> results = order_by(items, ['-a', 'b']) >>> assert results == [{'a': 3, 'b': 2},\ {'a': 2, 'b': 1},\ {'a': 1, 'b': 3}] >>> results = order_by(items, ['a', 'b'], [False, True]) >>> assert results == [{'a': 3, 'b': 2},\ {'a': 2, 'b': 1},\ {'a': 1, 'b': 3}] .. versionadded:: 3.0.0 .. versionchanged:: 3.2.0 Added `orders` argument. .. versionchanged:: 3.2.0 Added :func:`sort_by_order` as alias. .. versionchanged:: 4.0.0 Renamed from ``order_by`` to ``order_by`` and removed alias ``sort_by_order``. """ if isinstance(collection, dict): collection = collection.values() # Maintain backwards compatibility. if pyd.is_boolean(orders): reverse = orders orders = None comparers = [] if orders: for i, key in enumerate(keys): if pyd.has(orders, i): order = 1 if orders[i] else -1 else: order = 1 comparers.append((pyd.property_(key), order)) else: for key in keys: if key.startswith('-'): order = -1 key = key[1:] else: order = 1 comparers.append((pyd.property_(key), order)) def comparison(left, right): # pylint: disable=useless-else-on-loop,missing-docstring for func, mult in comparers: result = _cmp(func(left), func(right)) if result: return mult * result else: return 0 return sorted(collection, key=cmp_to_key(comparison), reverse=reverse)
def test_property_(case, arg, expected): assert _.map_(arg, _.property_(case)) == expected