summaryrefslogtreecommitdiff
path: root/game/python-extra/utils/dicts/helpers.py
diff options
context:
space:
mode:
Diffstat (limited to 'game/python-extra/utils/dicts/helpers.py')
-rw-r--r--game/python-extra/utils/dicts/helpers.py99
1 files changed, 99 insertions, 0 deletions
diff --git a/game/python-extra/utils/dicts/helpers.py b/game/python-extra/utils/dicts/helpers.py
new file mode 100644
index 0000000..8b1f594
--- /dev/null
+++ b/game/python-extra/utils/dicts/helpers.py
@@ -0,0 +1,99 @@
+from collections import namedtuple
+
+
+def from_keyed_iterable(iterable, key, filter_func=None):
+ """Construct a dictionary out of an iterable, using an attribute name as
+ the key. Optionally provide a filter function, to determine what should be
+ kept in the dictionary."""
+
+ generated = {}
+
+ for element in iterable:
+ try:
+ k = getattr(element, key)
+ except AttributeError:
+ raise RuntimeError("{} does not have the keyed attribute: {}".format(
+ element, key
+ ))
+
+ if filter_func is None or filter_func(element):
+ if k in generated:
+ generated[k] += [element]
+ else:
+ generated[k] = [element]
+
+ return generated
+
+
+def subtract_by_key(dict_a, dict_b):
+ """given two dicts, a and b, this function returns c = a - b, where
+ a - b is defined as the key difference between a and b.
+
+ e.g.,
+ {1:None, 2:3, 3:"yellow", 4:True} - {2:4, 1:"green"} =
+ {3:"yellow", 4:True}
+
+ """
+ difference_dict = {}
+ for key in dict_a:
+ if key not in dict_b:
+ difference_dict[key] = dict_a[key]
+
+ return difference_dict
+
+
+def subtract(dict_a, dict_b, strict=False):
+ """a stricter form of subtract_by_key(), this version will only remove an
+ entry from dict_a if the key is in dict_b *and* the value at that key
+ matches"""
+ if not strict:
+ return subtract_by_key(dict_a, dict_b)
+
+ difference_dict = {}
+ for key in dict_a:
+ if key not in dict_b or dict_b[key] != dict_a[key]:
+ difference_dict[key] = dict_a[key]
+
+ return difference_dict
+
+
+WinnowedResult = namedtuple("WinnowedResult", ['has', 'has_not'])
+def winnow_by_keys(dct, keys=None, filter_func=None):
+ """separates a dict into has-keys and not-has-keys pairs, using either
+ a list of keys or a filtering function."""
+ has = {}
+ has_not = {}
+
+ for key in dct:
+ key_passes_check = False
+ if keys is not None:
+ key_passes_check = key in keys
+ elif filter_func is not None:
+ key_passes_check = filter_func(key)
+
+ if key_passes_check:
+ has[key] = dct[key]
+ else:
+ has_not[key] = dct[key]
+
+ return WinnowedResult(has, has_not)
+
+
+def intersection(dict_a, dict_b, strict=True):
+ intersection_dict = {}
+
+ for key in dict_a:
+ if key in dict_b:
+ if not strict or dict_a[key] == dict_b[key]:
+ intersection_dict[key] = dict_a[key]
+
+ return intersection_dict
+
+
+def setdefaults(dct, defaults):
+ """Given a target dct and a dict of {key:default value} pairs,
+ calls setdefault for all of those pairs."""
+ for key in defaults:
+ dct.setdefault(key, defaults[key])
+
+ return dct