Reputation: 27
Below is an example of a complicated dictionary that I am looping through. I want to check if "AccountRoot" appears in the dictionary. Be aware that I am looping through many of these dictionaries and the format changes. Thus I was wondering if there was a function like .find()
. I could not find any and it seems like .find()
does not work.
Example Dict;
{'hash': '752F3B5CEE85F3C2DC60041DCAC4777BECE9CC11585225383F8178EBC2ACFB16',
'ledger_index': 108843,
'date': '2013-01-18T22:27:20+00:00',
'tx': {'TransactionType': 'OfferCreate',
'Flags': 0,
'Sequence': 3,
'TakerPays': '499950000',
'TakerGets': {'value': '0.05',
'currency': 'BTC',
'issuer': 'r4aZ4aqXHfrcYfuFrTqDmSopfgPHnRS9MZ'},
'Fee': '10',
'SigningPubKey': '027008A4A7AED7B5426EAC46691CFCAC8CA3CF2773D1CAC4074F0BC58EC24BE883',
'TxnSignature': '3046022100C38236B533936B4A328346D5246570976B8A1390655EC1B6F4090C42AE73FD8D022100D49E5498C40D90AF7BD02F2818EE04F1D0F6B0C76F0325997190D56BF4B9D82D',
'Account': 'r4aZ4aqXHfrcYfuFrTqDmSopfgPHnRS9MZ'},
'meta': {'TransactionIndex': 0,
'AffectedNodes': [{'CreatedNode': {'LedgerEntryType': 'DirectoryNode',
'LedgerIndex': '0A624575D3C02D544B92F23F6A8BDF3B10745427B731613820A1695AFF11993B',
'NewFields': {'ExchangeRate': '5E2386099B1BF000',
'RootIndex': '0A624575D3C02D544B92F23F6A8BDF3B10745427B731613820A1695AFF11993B',
'TakerGetsCurrency': '0000000000000000000000004254430000000000',
'TakerGetsIssuer': 'E767BCB9E1A31C46C16F42DA9DDE55792767F565'}}},
{'CreatedNode': {'LedgerEntryType': 'DirectoryNode',
'LedgerIndex': '165845E192D2217A6518C313F3F4B2FD676EE1619FF50CB85E2386099B1BF000',
'NewFields': {'ExchangeRate': '5E2386099B1BF000',
'RootIndex': '165845E192D2217A6518C313F3F4B2FD676EE1619FF50CB85E2386099B1BF000',
'TakerGetsCurrency': '0000000000000000000000004254430000000000',
'TakerGetsIssuer': 'E767BCB9E1A31C46C16F42DA9DDE55792767F565'}}},
{'ModifiedNode': {'LedgerEntryType': 'AccountRoot',
'PreviousTxnLgrSeq': 108839,
'PreviousTxnID': '8B2921C5222A6814BCF7602A18FEACE94797A644AF893A43FB642C172CC14ED0',
'LedgerIndex': '481DA662E465CC7888FD3750A0952F2003D78DCAA8CB2E91088E862BB7D30B98',
'PreviousFields': {'Sequence': 3,
'OwnerCount': 0,
'Balance': '9999999980'},
'FinalFields': {'Flags': 0,
'Sequence': 4,
'OwnerCount': 1,
'Balance': '9999999970',
'Account': 'r4aZ4aqXHfrcYfuFrTqDmSopfgPHnRS9MZ'}}},
{'CreatedNode': {'LedgerEntryType': 'Offer',
'LedgerIndex': '9AABB5DCD201AE7FB0F9B7F90083F48B7451977B2419339ADFEBD8876B54EB66',
'NewFields': {'Sequence': 3,
'BookDirectory': '165845E192D2217A6518C313F3F4B2FD676EE1619FF50CB85E2386099B1BF000',
'TakerPays': '499950000',
'TakerGets': {'value': '0.05',
'currency': 'BTC',
'issuer': 'r4aZ4aqXHfrcYfuFrTqDmSopfgPHnRS9MZ'},
'Account': 'r4aZ4aqXHfrcYfuFrTqDmSopfgPHnRS9MZ'}}}],
'TransactionResult': 'tesSUCCESS'}}
Upvotes: 0
Views: 66
Reputation: 1578
Answer here: Finding a key recursively in a dictionary
Posting this so people can encounter the answer if they search using different terms.
I would use alecxe's answer using the stack of iterators pattern defined here by Gareth Rees: http://garethrees.org/2016/09/28/pattern/
Code in case other links are destroyed:
def search(d, key, default=None):
"""
Return a value corresponding to the specified key in the (possibly
nested) dictionary d. If there is no item with that key, return
default.
"""
stack = [iter(d.items())]
while stack:
for k, v in stack[-1]:
if isinstance(v, dict):
stack.append(iter(v.items()))
break
elif k == key:
return v
else:
stack.pop()
return default
This code allows you to avoid the problem of exceeding the maximum recursion depth present in some other solutions.
Edit: realized you're simply trying to find out if a value exists in the dictionary.
You can simply modify the for loop to something like this, and it should work for a simple true/false search.
def search(d, key, default=False):
"""
Return a value corresponding to the specified key in the (possibly
nested) dictionary d. If there is no item with that key, return
default.
"""
stack = [iter(d.items())]
while stack:
for k, v in stack[-1]:
if isinstance(v, dict):
stack.append(iter(v.items()))
break
elif k == key:
return True
elif v == key:
return True
else:
stack.pop()
return default
Upvotes: 2
Reputation: 2217
There's potentially an easier way, but here's how I've done something similar. I've modified it for your use case.
import copy
def traverse_dict(_obj):
_obj_2 = copy.deepcopy(_obj)
if isinstance(_obj_2, dict):
for key, value in _obj_2.items():
if key == 'your_value':
do_your_stuff()
_obj_2[key] = traverse_dict(value)
elif isinstance(_obj, list):
for offset in range(len(_obj_2)):
_obj_2[offset] = traverse_dict(_obj_2[offset])
return _obj_2
Upvotes: 0