Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/cardinal_pythonlib/lists.py : 37%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1#!/usr/bin/env python
2# cardinal_pythonlib/lists.py
4"""
5===============================================================================
7 Original code copyright (C) 2009-2021 Rudolf Cardinal (rudolf@pobox.com).
9 This file is part of cardinal_pythonlib.
11 Licensed under the Apache License, Version 2.0 (the "License");
12 you may not use this file except in compliance with the License.
13 You may obtain a copy of the License at
15 https://www.apache.org/licenses/LICENSE-2.0
17 Unless required by applicable law or agreed to in writing, software
18 distributed under the License is distributed on an "AS IS" BASIS,
19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 See the License for the specific language governing permissions and
21 limitations under the License.
23===============================================================================
25**Functions for dealing with lists.**
27"""
29from collections import Counter
30from operator import itemgetter
31from typing import Any, Callable, Iterable, List, Tuple
34# =============================================================================
35# Lists and similar
36# =============================================================================
38def contains_duplicates(values: Iterable[Any]) -> bool:
39 """
40 Does the iterable contain any duplicate values?
41 """
42 for v in Counter(values).values():
43 if v > 1:
44 return True
45 return False
48def index_list_for_sort_order(x: List[Any], key: Callable[[Any], Any] = None,
49 reverse: bool = False) -> List[int]:
50 """
51 Returns a list of indexes of ``x``, IF ``x`` WERE TO BE SORTED.
53 Args:
54 x: data
55 key: function to be applied to the data to generate a sort key; this
56 function is passed as the ``key=`` parameter to :func:`sorted`;
57 the default is ``itemgetter(1)``
58 reverse: reverse the sort order?
60 Returns:
61 list of integer index values
63 Example:
65 .. code-block:: python
67 z = ["a", "c", "b"]
68 index_list_for_sort_order(z) # [0, 2, 1]
69 index_list_for_sort_order(z, reverse=True) # [1, 2, 0]
70 q = [("a", 9), ("b", 8), ("c", 7)]
71 index_list_for_sort_order(q, key=itemgetter(1))
73 """
74 def key_with_user_func(idx_val: Tuple[int, Any]):
75 return key(idx_val[1])
76 if key:
77 sort_key = key_with_user_func
78 # see the simpler version below
79 else:
80 sort_key = itemgetter(1)
81 # enumerate, below, will return tuples of (index, value), so
82 # itemgetter(1) means sort by the value
83 index_value_list = sorted(enumerate(x), key=sort_key, reverse=reverse)
84 return [i for i, _ in index_value_list]
87def sort_list_by_index_list(x: List[Any], indexes: List[int]) -> None:
88 """
89 Re-orders ``x`` by the list of ``indexes`` of ``x``, in place.
91 Example:
93 .. code-block:: python
95 from cardinal_pythonlib.lists import sort_list_by_index_list
97 z = ["a", "b", "c", "d", "e"]
98 sort_list_by_index_list(z, [4, 0, 1, 2, 3])
99 z # ["e", "a", "b", "c", "d"]
100 """
101 x[:] = [x[i] for i in indexes]
104def flatten_list(x: List[Any]) -> List[Any]:
105 """
106 Converts a list of lists into a flat list.
108 Args:
109 x: list of lists
111 Returns:
112 flat list
114 As per
115 https://stackoverflow.com/questions/952914/making-a-flat-list-out-of-list-of-lists-in-python
117 """ # noqa
118 return [item for sublist in x for item in sublist]
121def unique_list(seq: Iterable[Any]) -> List[Any]:
122 """
123 Returns a list of all the unique elements in the input list.
125 Args:
126 seq: input list
128 Returns:
129 list of unique elements
131 As per
132 https://stackoverflow.com/questions/480214/how-do-you-remove-duplicates-from-a-list-in-whilst-preserving-order
134 """ # noqa
135 seen = set()
136 seen_add = seen.add
137 return [x for x in seq if not (x in seen or seen_add(x))]
140def chunks(x: List[Any], n: int) -> Iterable[List[Any]]:
141 """
142 Yield successive ``n``-sized chunks from the list ``x``.
144 Args:
145 x: input list
146 n: chunk size
148 Yields:
149 successive chunks of size ``n``
151 """
152 for i in range(0, len(x), n):
153 yield x[i:i + n]
156def count_bool(blist: Iterable[Any]) -> int:
157 """
158 Counts the number of "truthy" members of the input list.
160 Args:
161 blist: list of booleans or other truthy/falsy things
163 Returns:
164 number of truthy items
166 """
167 return sum([1 if x else 0 for x in blist])