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
mapping
oriterable
. If an iterable, its elements are iterables of length 2. (Note that passingNone
is 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 ofNone
is different to supplying no default.
- setdefault(key: Any, default: Any | None = None) Any [source]
As per the Python docs:
If
key
is in the dictionary, return its value. If not, insertkey
with a value ofdefault
and returndefault
.default
defaults 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
/**kwargs
options.
- 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
/**kwargs
parts 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
d1
to created2
.- Parameters:
- Returns:
a dictionary of the format
{k: v}
where thek
/v
pairs are key/value pairs that are absent fromd1
and present ind2
, or present in both but with different values (in which case thed2
value is shown). If a keyk
is present ind1
but 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 (orNone
if 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
d
dictionary contains akey -> value
mapping.We start with a list of potential keys in
keys
, and return a list of corresponding values – substitutingdefault
if any are missing, or raisingKeyError
ifraise_if_missing
is true, or omitting the entry ifomit_if_missing
is 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
d
but withprefix
prepended to its keys.
- cardinal_pythonlib.dicts.rename_key(d: Dict[str, Any], old: str, new: str) None [source]
Rename a key in dictionary
d
fromold
tonew
, 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
d
with its keys renamed according tomapping
.- Parameters:
- Returns:
a new dictionary
Keys that are not in
mapping
are 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
d
according to the mapping inrenames
.- Parameters:
See https://stackoverflow.com/questions/4406501/change-the-name-of-a-key-in-dictionary.