I have a dict that looks like this:
OrderedDict([('arguments', {'index': 1, 'parent': None}), ('controls', {'index': 2, 'parent': None}), ('examples', {'index': 3, 'parent': None}), ('journal', {'index': 4, 'parent': None}), ('journal/config', {'index': 5, 'parent': 'journal'}), ('journal/journaltest', {'index': 6, 'parent': 'journal'}), ('procs', {'index': 7, 'parent': None}), ('processor', {'index': 8, 'parent': None}), ('prediction', {'index': 9, 'parent': None}), ('reports', {'index': 10, 'parent': None}), ('tooki', {'index': 11, 'parent': None}), ('tooki/help', {'index': 12, 'parent': 'tooki'}), ('tooki/lime', {'index': 13, 'parent': 'tooki'}), ('tooki/medium', {'index': 14, 'parent': 'tooki'}), ('tooki/share', {'index': 15, 'parent': 'tooki'}), ('tooki/trigger', {'index': 16, 'parent': 'tooki'})])
How can I iterate over the elements of this dict, and exclude any element that has "'parent' : None" and no child element (meaning, no other element in this dict has this one as a parent).
Expected output:
OrderedDict([('journal', {'index': 4, 'parent': None}), ('journal/config', {'index': 5, 'parent': 'journal'}), ('journal/journaltest', {'index': 6, 'parent': 'journal'}), ('tooki', {'index': 11, 'parent': None}), ('tooki/help', {'index': 12, 'parent': 'tooki'}), ('tooki/lime', {'index': 13, 'parent': 'tooki'}), ('tooki/medium', {'index': 14, 'parent': 'tooki'}), ('tooki/share', {'index': 15, 'parent': 'tooki'}), ('tooki/trigger', {'index': 16, 'parent': 'tooki'})])
CodePudding user response:
ins = OrderedDict(...)
parents = set(elem['parent'] for elem in ins.values() if elem['parent'] is not None)
d = OrderedDict()
for key, value in ins.items():
if value['parent'] is not None:
d[key] = value
elif any(ins.get(k) is not None for k in parents):
d[key] = value
Using a set of parent keys remove lot of complexity. In your case, there are lot of elements, but only two keys will be checked.
CodePudding user response:
A really dumb way of doing this:
x = OrderedDict(blah blah blah)
keys_to_exclude = []
for key1, val1 in x.items():
if val1['parent'] is None:
remove = True
for key2, val2 in x.items():
if val2['parent'] == key1:
remove = False
if remove:
keys_to_exclude.append(key1)
for key in keys_to_exclude:
x.pop(key, None)
This code obviously had O(n^2) complexity. A smarter way of doing this would be adding a 'child' key for each element beforehand and the complexity would be O(n).
CodePudding user response:
Here is something that working for me. The order of the final output is not the same, but I was able to meet the requirement of excluding the key value
pairs according to the conditions you had mentioned.
a = OrderedDict([('arguments', {'index': 1, 'parent': None}),
('controls', {'index': 2, 'parent': None}),
('examples', {'index': 3, 'parent': None}),
('journal', {'index': 4, 'parent': None}),
('journal/config', {'index': 5, 'parent': 'journal'}),
('journal/journaltest', {'index': 6, 'parent': 'journal'}),
('procs', {'index': 7, 'parent': None}),
('processor', {'index': 8, 'parent': None}),
('prediction', {'index': 9, 'parent': None}),
('reports', {'index': 10, 'parent': None}),
('tooki', {'index': 11, 'parent': None}),
('tooki/help', {'index': 12, 'parent': 'tooki'}),
('tooki/lime', {'index': 13, 'parent': 'tooki'}),
('tooki/medium', {'index': 14, 'parent': 'tooki'}),
('tooki/share', {'index': 15, 'parent': 'tooki'}),
('tooki/trigger', {'index': 16, 'parent': 'tooki'})])
od = OrderedDict()
for each in a:
if (parent := a[each].get('parent', None)):
od[parent] = a[parent]
for each in a:
if (element := a[each].get('parent', None)):
od[each] = a[each]
print(od)
I did not comprehension for simplicity of understanding the code. The first loop saves the parents to a new OrdereDict
. The second saves the children. Do let me know if your requirements are not met.