cardinal_pythonlib.dicts
Original code copyright (C) 2009-2022 Rudolf Cardinal (rudolf@pobox.com).
This file is part of cardinal_pythonlib.
Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Dictionary manipulations.
- class cardinal_pythonlib.dicts.CaseInsensitiveDict(*args, **kwargs)[source]
A case-insensitive dictionary, as per https://stackoverflow.com/questions/2082152/case-insensitive-dictionary/32888599#32888599, with updates for Python 3 and type hinting.
See also
https://docs.python.org/3/tutorial/datastructures.html#dictionaries
https://docs.python.org/3/library/stdtypes.html#mapping-types-dict
Test code:
from cardinal_pythonlib.dicts import CaseInsensitiveDict d1 = CaseInsensitiveDict() # d1 is now: {} d2 = CaseInsensitiveDict({'A': 1, 'b': 2}) # d2 is now: {'a': 1, 'b': 2} d3 = CaseInsensitiveDict(C=3, d=4) # d3 is now: {'c': 3, 'd': 4} d1.update({'E': 5, 'f': 6}) # d1 is now: {'e': 5, 'f': 6} d1.update(G=7, h=8) # d1 is now: {'e': 5, 'f': 6, 'g': 7, 'h': 8} 'H' in d1 # True d1['I'] = 9 # None, and key 'i' added del d1['I'] # None, and key 'i' deleted d1.pop('H') # 8 d1.get('E') # 5 d1.get('Z') # None d1.setdefault('J', 10) # 10, and key 'j' added d1.update([('K', 11), ('L', 12)]) d1 # {'e': 5, 'f': 6, 'g': 7, 'j': 10, 'k': 11, 'l': 12}
Dictionary initialization.
Optional positional argument is
mappingoriterable. If an iterable, its elements are iterables of length 2. (Note that passingNoneis different from not passing anything, hence the signature. The type of the first argument, if present, isUnion[Mapping, Iterable[Tuple[Any, Any]]].)Keyword arguments are key/value pairs.
- get(key: Any, default: Any | None = None) Any[source]
If the key is in the dictionary, return the corresponding value; otherwise, return
default, which defaults toNone.
- pop(key: Any, *args, **kwargs) Any[source]
Retrieves/returns the item and removes it. Takes a single optional argument, being the default to return if the key is not present (otherwise raises
KeyError). Note that supplying a default ofNoneis different to supplying no default.
- setdefault(key: Any, default: Any | None = None) Any[source]
As per the Python docs:
If
keyis in the dictionary, return its value. If not, insertkeywith a value ofdefaultand returndefault.defaultdefaults toNone.
- update(*args, **kwargs) None[source]
As per the Python docs:
Update the dictionary with the key/value pairs from
other, overwriting existing keys. ReturnNone.update``accepts either another dictionary object or an iterable of key/value pairs (as tuples or other iterables of length two). If keyword arguments are specified, the dictionary is then updated with those key/value pairs: ``d.update(red=1, blue=2)`().… so the type of the first argument, if present, is
Union[Mapping, .Iterable[Tuple[Any, Any]]].
- class cardinal_pythonlib.dicts.HashableDict[source]
A dictionary that can be hashed.
See https://stackoverflow.com/questions/1151658/python-hashable-dicts.
- class cardinal_pythonlib.dicts.LazyButHonestDict[source]
A dictionary that provides alternatives to
get()andsetdefault(), namelylazyget()andlazysetdefault(), that only evaluate their arguments if they have to.See https://stackoverflow.com/questions/17532929/how-to-implement-a-lazy-setdefault.
Compared to the StackOverflow version: no obvious need to have a default returning
None, when we’re implementing this as a special function. In contrast, helpful to have*args/**kwargsoptions.
- class cardinal_pythonlib.dicts.LazyDict[source]
A dictionary that only evaluates the argument to
setdefault()orget()if it needs to.See https://stackoverflow.com/questions/17532929/how-to-implement-a-lazy-setdefault.
The
*args/**kwargsparts are useful, but we don’t want to have to name ‘thunk’ explicitly.
- cardinal_pythonlib.dicts.delete_keys(d: Dict[Any, Any], keys_to_delete: List[Any], keys_to_keep: List[Any]) None[source]
Deletes keys from a dictionary, in place.
- cardinal_pythonlib.dicts.dict_diff(d1: Dict[Any, Any], d2: Dict[Any, Any], deleted_value: Any | None = None) Dict[Any, Any][source]
Returns a representation of the changes that need to be made to
d1to created2.- Parameters:
- Returns:
a dictionary of the format
{k: v}where thek/vpairs are key/value pairs that are absent fromd1and present ind2, or present in both but with different values (in which case thed2value is shown). If a keykis present ind1but absent ind2, the result dictionary has the entry{k: deleted_value}.- Return type:
dict
- cardinal_pythonlib.dicts.get_case_insensitive_dict_key(d: Dict, k: str) str | None[source]
Within the dictionary
d, find a key that matches (in case-insensitive fashion) the keyk, and return it (orNoneif there isn’t one).
- cardinal_pythonlib.dicts.map_keys_to_values(keys: List[Any], d: Dict[Any, Any], default: Any | None = None, raise_if_missing: bool = False, omit_if_missing: bool = False) List[Any][source]
The
ddictionary contains akey -> valuemapping.We start with a list of potential keys in
keys, and return a list of corresponding values – substitutingdefaultif any are missing, or raisingKeyErrorifraise_if_missingis true, or omitting the entry ifomit_if_missingis true.
- cardinal_pythonlib.dicts.merge_dicts(*dict_args: Dict) Dict[source]
Given any number of dicts, shallow-copy them and merge into a new dict. Precedence goes to key/value pairs in dicts that are later in the list.
- cardinal_pythonlib.dicts.merge_two_dicts(x: Dict, y: Dict) Dict[source]
Given two dicts, merge them into a new dict as a shallow copy, e.g.
z = merge_two_dicts(x, y)
If you can guarantee Python 3.5, then a simpler syntax is:
z = {**x, **y}
- cardinal_pythonlib.dicts.prefix_dict_keys(d: Dict[str, Any], prefix: str) Dict[str, Any][source]
Returns a dictionary that’s a copy of as
dbut withprefixprepended to its keys.
- cardinal_pythonlib.dicts.rename_key(d: Dict[str, Any], old: str, new: str) None[source]
Rename a key in dictionary
dfromoldtonew, in place.
- cardinal_pythonlib.dicts.rename_keys(d: Dict[str, Any], mapping: Dict[str, str]) Dict[str, Any][source]
Returns a copy of the dictionary
dwith its keys renamed according tomapping.- Parameters:
- Returns:
a new dictionary
Keys that are not in
mappingare left unchanged. The input parameters are not modified.
- cardinal_pythonlib.dicts.rename_keys_in_dict(d: Dict[str, Any], renames: Dict[str, str]) None[source]
Renames, IN PLACE, the keys in
daccording to the mapping inrenames.- Parameters:
See https://stackoverflow.com/questions/4406501/change-the-name-of-a-key-in-dictionary.