lkj 0.1.39__py3-none-any.whl → 0.1.41__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
lkj/__init__.py CHANGED
@@ -13,6 +13,7 @@ from lkj.dicts import (
13
13
  inclusive_subdict, # new dictionary with only the keys in `include`
14
14
  exclusive_subdict, # new dictionary with only the keys not in `exclude`.
15
15
  merge_dicts, # Merge multiple dictionaries recursively
16
+ compare_field_values, # Compare two dictionaries' values
16
17
  )
17
18
  from lkj.filesys import get_app_data_dir, get_watermarked_dir, enable_sourcing_from_file
18
19
  from lkj.strings import (
lkj/dicts.py CHANGED
@@ -111,16 +111,10 @@ from typing import Mapping, Callable, TypeVar, Iterable, Tuple
111
111
  KT = TypeVar("KT") # Key type
112
112
  VT = TypeVar("VT") # Value type
113
113
 
114
+
114
115
  # Note: Could have all function parameters (recursive_condition, etc.) also take the
115
116
  # enumerated index of the mapping as an argument. That would give us even more
116
117
  # flexibility, but it might be overkill and make the interface more complex.
117
- from typing import Mapping, Callable, TypeVar, Iterable, Tuple
118
- from collections import defaultdict
119
-
120
- KT = TypeVar("KT") # Key type
121
- VT = TypeVar("VT") # Value type
122
-
123
-
124
118
  def merge_dicts(
125
119
  *mappings: Mapping[KT, VT],
126
120
  recursive_condition: Callable[[VT], bool] = lambda v: isinstance(v, Mapping),
@@ -221,3 +215,62 @@ def merge_dicts(
221
215
  merged[key] = value
222
216
 
223
217
  return merged
218
+
219
+
220
+ import operator
221
+ from typing import Callable, Dict, Any
222
+
223
+ Comparison = Any
224
+ Comparator = Callable[[dict, dict], Comparison]
225
+
226
+
227
+ def compare_field_values(
228
+ dict1,
229
+ dict2,
230
+ *,
231
+ field_comparators: Dict[KT, Comparator] = {},
232
+ default_comparator: Comparator = operator.eq,
233
+ aggregator: Callable[
234
+ [Dict[KT, Comparison]], Any
235
+ ] = lambda d: d, # lambda d: np.mean(list(d.values()))
236
+ ):
237
+ """
238
+ Compare two dictionaries' values field by field
239
+
240
+ :param dict1: The first dictionary.
241
+ :param dict2: The second dictionary.
242
+ :param field_comparators: A dictionary where keys are field names and values are comparator functions.
243
+ :param default_comparator: A default comparator function to use if no specific comparator is provided for a field.
244
+ :param aggregator: A function to aggregate the comparison results into a final comparison object.
245
+ :return: A final score based on the comparison results.
246
+
247
+ >>> dict1 = {"color": "brown", "animal": "dog"}
248
+ >>> dict2 = {"color": "brown", "animal": "cat"}
249
+ >>> dict3 = {"color": "brown", "animal": "bird"}
250
+ >>> field_comparators = {
251
+ ... "color": lambda x, y: 1 if x == y else 0,
252
+ ... "animal": lambda x, y: 1 if len(x) == len(y) else 0
253
+ ... }
254
+ >>> compare_field_values(dict1, dict2, field_comparators=field_comparators)
255
+ {'color': 1, 'animal': 1}
256
+ >>> compare_field_values(dict1, dict3, field_comparators=field_comparators)
257
+ {'color': 1, 'animal': 0}
258
+ >>> import functools, statistics
259
+ >>> aggregator = lambda d: statistics.mean(d.values())
260
+ >>> mean_of_values = functools.partial(
261
+ ... compare_field_values, field_comparators=field_comparators, aggregator=aggregator
262
+ ... )
263
+ >>> mean_of_values(dict1, dict2)
264
+ 1
265
+ >>> mean_of_values(dict1, dict3)
266
+ 0.5
267
+
268
+ """
269
+ common_keys = [k for k in dict1.keys() if k in dict2.keys()]
270
+
271
+ comparisons = {}
272
+ for key in common_keys:
273
+ comparator = field_comparators.get(key, default_comparator)
274
+ comparisons[key] = comparator(dict1[key], dict2[key])
275
+
276
+ return aggregator(comparisons)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lkj
3
- Version: 0.1.39
3
+ Version: 0.1.41
4
4
  Summary: A dump of homeless useful utils
5
5
  Home-page: https://github.com/thorwhalen/lkj
6
6
  Author: Thor Whalen
@@ -1,6 +1,6 @@
1
- lkj/__init__.py,sha256=YEPCVj-0EJOfpapgX3Vw07399w13OkCm39KCmCi5AQg,6806
1
+ lkj/__init__.py,sha256=Vceal0uY2jW1y0sQHOk1WHXc9aTAEXXOJ9vgyOmnrNk,6868
2
2
  lkj/chunking.py,sha256=RpNdx5jEuO4mFg2qoTkD47iL35neBneuZ5xgQ_cBkiM,3755
3
- lkj/dicts.py,sha256=EbTLtYlexCDhDlwKnzflZ5CEU0ql6KgZdu3SvR7bU20,8289
3
+ lkj/dicts.py,sha256=vmdOXgGVWe3LTz40dHamj7-c8ob4B5SxL3zPJcylf40,10216
4
4
  lkj/filesys.py,sha256=NbWDuc848h8O42gwX7d9yNJkrWBgzSFnkoEdSRgvBAg,8883
5
5
  lkj/funcs.py,sha256=LXJlj3gMMsbD0t2gn2NZZ6mOqmW5bxM-94uGoYgrhzI,8930
6
6
  lkj/importing.py,sha256=_BFBmdaKCBnk5broltWDeAPeEKG1dEkS8DhIdv6UhSI,3809
@@ -8,8 +8,8 @@ lkj/iterables.py,sha256=9jeO36w-IGiZryge7JKgXZOGZAgehUvhwKV3nHPcZWk,2801
8
8
  lkj/loggers.py,sha256=ImmBdacz89Lvb3dg_xI5jOct_44rSRv0hNI_CVehy60,13706
9
9
  lkj/misc.py,sha256=IZf05tkl0cgiMgBwCMH5cLSC59fRXwnemPRo8G0OxQg,1436
10
10
  lkj/strings.py,sha256=3YjlxOWUfzWqwu51uq_pv9XZReLqRFvziGtRsdzEtw8,24662
11
- lkj-0.1.39.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
12
- lkj-0.1.39.dist-info/METADATA,sha256=FFVXFg-ElX-E_xQRF9i8IExOOqEgIScsqigQTu0vtdM,4684
13
- lkj-0.1.39.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
14
- lkj-0.1.39.dist-info/top_level.txt,sha256=3DZOUwYmyurJFBXQCvCmEIVm8z2b42O5Sx3RDQyePfg,4
15
- lkj-0.1.39.dist-info/RECORD,,
11
+ lkj-0.1.41.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
12
+ lkj-0.1.41.dist-info/METADATA,sha256=Tc9RoFOGPs137L9Mw1--sGkVEtmc455ZLx2lHRMqUDc,4684
13
+ lkj-0.1.41.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
14
+ lkj-0.1.41.dist-info/top_level.txt,sha256=3DZOUwYmyurJFBXQCvCmEIVm8z2b42O5Sx3RDQyePfg,4
15
+ lkj-0.1.41.dist-info/RECORD,,
File without changes
File without changes