简体   繁体   中英

Replace list of values of dictionary

Given a dictionary with a list of list as values how to replace some of the sublists in values list given a particular criteria.

So far what I've tried is to iterate over all sublists by length and estimate the commom value in both sublists.

For instance, given the following dictionary:

d = {(1, 2): [[0, 14], [3]], (10, 12): [[9, 11], [13]]}

and a sublist to compare with:

candidates = [14,9]

I would expect for my output to be :

d = {(1, 2): [14, 3], (10, 12): [9, 13]}

What I tried so far is to iterate over all sublists by length and replace for the intersection of both sublists:

for k,v in d.items():
    for l in v():
        if len(l) > 1:
            v = list(set(l).intersection(candidates)))

The output represent the commom elements between candidates list and those sublists whose length are > 1. As a result the sublist [0,14] would be replaced by [14] which is the commom element. This sublist [4] can be eventually be merged with [3] list on the same key. Resulting in [14,3] . The same logic holds for the second key and list of sublists

But I am bit stuck in updating the dict by keeping and eventually merging that sublists that whose lenght are < 1.

Any hint?

You can use a dict comprehension that iterates over the dict items and use a nested list comprehension to iterate over the sub-lists, and for each sub-sub-list in a sub-list with length greater than 1, use set intersection with the candidates:

{k: [i for s in l for i in (set(s).intersection(candidates) if len(s) > 1 else s)] for k, l in d.items()}

This returns:

{(1, 2): [14, 3], (10, 12): [9, 13]}

If you want to update a list, which is possible because a list is a mutable type, you must directly change an element. If you pass through an intermediary variable, you just assign a new value to that variable:

Demo:

l = [1,2,3]
for i in l:
    i = 0        # only changes i, no effect on l

l = [1,2,3]
for i, j in enumerate(l):
    l[j] = 0     # actually changes l

For the merging part, I will just assume that you merge if all lists under a key have length <= 1:

for k,v in d.items():
    merge = True
    for i,l in enumerate(v):
        if len(l) > 1:
            v[i] = list(set(l).intersection(candidates))
        if len(v[i]) > 1:
            merge = False
    if merge:
        d[k] = [l[0] for l in v]

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