Reputation: 22093
I have such following a dict and a list.
mylist= ['1H1.PyModule.md',
'1H2.Class.md',
'1H3.MetaObject.md',
'2B1D0.Data.md',
'2B1D1.Primitive.md',
'2B1D2.Operator.md',
'2B2D3.Container.md',
'2B2S0.Function.md',
'2B2S0.Statemment.md',
'2B2S1.Controlled_Loop.md',
'2B2S2.Conditions.md',
'2B2S3.Except.md',
...
]
mydict = {'Body': {'Data': ['1.primitive', '2.operator', '3.container'],
'Statement': ['0.function', '1.controlled_loop', '2.condition', '3.except']},
'Header': ['1.Modle', '2.Class', '3.Object'],
...}
I attempt to repalce the strings in mydict
with the appropriate in mylist
I can figure out '2B1D0.Data.md'
has the shortest length,
So I slice the keyward 'Data'
In [82]: '2B1D0.Data.md'[-7:-3]
Out[82]: 'Data'
The dict has both a nested list and nested dict.
So I write a iteration function with type checking
if an item's value isinstance(value,list)
, renew that value,
if an item's value isinstance(value, dict)
,call the function replace_ele()
to continue.
I name string in mylist as str_of_list, while string in mydict as str_of_dict for readable concerns.
#replace one string in mydict
def replace_ele(mydict, str_of_list):
for key, value in mydict.items():
if isinstance(value, list): #type checking
for str_of_dict in value:
#replace str_of_dict with str_of_list
if str_of_list[-7:-3].lower() == str_of_dict[-4:]: #[-7:-3] the shortest length
value.remove(str_of_dict)
value.append(str_of_list)
value.sort()
mydict[key] = value
#iteration if a dict
if isinstance(value, dict):
replace_ele(value,str_of_list)
for str_of_list in mylist:
replace_ele(mydict, str_of_list)
Then running and outputs:
Out[117]:
{'Body': {'Data': ['2B1D1.Primitive.md',
'2B1D2.Operator.md',
'2B2D3.Container.md'],
'Statement': ['2B2S0.Function.md',
'2B2S0.Function.md',
'2B2S1.Controlled_Loop.md',
'2B2S3.Except.md']},
'Header': ['1.Modle', '1H2.Class.md', '1H3.MetaObject.md']
....}
I assume that such a problem can be solved with less codes. However, I cannot find that solution with the limited knowledge.
How to accomplish it elegantly?
Upvotes: 1
Views: 110
Reputation: 18940
My suggestion is that you create a function to reduce element of mylist
and elements in lists of mydict
values to the same format:
For example, you can split by '.'
character, take the second field, convert it to lower case:
def f(s):
return s.split('.')[1].lower()
E.g.:
>>> f('2B2S1.Controlled_Loop.md')
'controlled_loop'
>>> f('1.controlled_loop')
'controlled_loop'
Now, from mylist
create a dict to hold replacements:
mylist_repl={f(x): x for x in mylist}
i.e. mylist_repl
contains key: value
items such as 'metaobject': '1H3.MetaObject.md'
.
With dict mylist_repl
and function f
, it is easy to transform a list from mydict
to the desired value, example:
>>> [mylist_repl[f(x)] for x in ['1.primitive', '2.operator', '3.container']]
['2B1D1.Primitive.md', '2B1D2.Operator.md', '2B2D3.Container.md']
Also note that this dictionary lookup is more efficient (i.e.: faster) than a nested for loop!
If you have different replacement logic, you probably only need to change how f
maps items from two different sets to a common key.
Upvotes: 2