简体   繁体   中英

How can I iterate through a dictionary whose length changes in python?

I have a dictionary that I want to iterate through and change its value but I think the change of length might cause error, is there any good ways to do this?

example:

d = {'a':'orange','b':'pineapple','c':'dragonfruit'}
rating = {'orange':3, 'pineapple':4, 'dragonfruit':4.5, 'apple':3, 'pear': 3.5}

for key, value in d.items():
    if some conditions met:
        del d['a'] or d['e']='apple' # (or is not operator, i mean literally one of the operation add or delete item...)

for example:

for key, value in d.items():
    if rating[value]<4:
        del d[key]

or

d = {'a':['orange'],'b':['pineapple','peach'],'c':['dragonfruit']}
rating = {'orange':3, 'pineapple':4, 'dragonfruit':4.5, 'apple':3, 'pear': 3.5, 'peach': 5}
for key, value in d.items():
    rating_sum = sum([ rating[v] for v in value])
    if rating_sum > 8 and len(value)>1:
        d['e'] = d[key].pop(-1)

probably not the best example... means the dictionary's length changes in the loop.

Don't add or remove keys while you iterate your dictionary. Also, do not shadow built-in dict .

You can use a dictionary comprehension with all your conditions:

d = {k: v for k, v in d.items() if \
     not (conditions and \
     ((k == 'a') or ((k, v) == ('e', 'apple'))))}

I presume your conditions are a function of k and v , otherwise you should calculate and apply this test outside of the dictionary comprehension.

But this can get a bit messy, so there's no harm in separating your logic into a function:

def keep_pair(k, v):
    if conditions:
        if (k == 'a') or ((k, v) == ('e', 'apple')):
            return False
    return True

d = {k, v for k, v in d.items() if keep_pair(k, v)}

You can copy your dict to some temporary dict variable and then iterate through the temporary dict but making changes to the original.

temp = dict.copy()

for key, value in temp.items():
    if some conditions met:
        del dict['a'] or dict['e']='apple'

Don't. It's not impossible but in most cases there's no reason to not build a new dictionary and reassign the name, which is easier to write and read.

d = <SOME-DICT>
# filter d with dict comprehension, reassign the name d
d = {k:v for k,v in d.items() if <FILTERING-CONDITION>}

Some demos::

>>> d = {'a':'orange','b':'pineapple','c':'dragonfruit'}
>>> {k:v for k,v in d.items() if v != 'pineapple'}
{'a': 'orange', 'c': 'dragonfruit'}
>>> {k:v for k,v in d.items() if not (k == 'd' and v == 'dragonfruit')}
{'a': 'orange', 'b': 'pineapple', 'c': 'dragonfruit'}
>>> {k:v for k,v in d.items() if not (k == 'c' and v == 'dragonfruit')}
{'a': 'orange', 'b': 'pineapple'}
>>> {k:v for k,v in d.items() if not (k == 'a' or (k == 'e' and v == 'pineapple'))}
{'b': 'pineapple', 'c': 'dragonfruit'}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM