简体   繁体   中英

Flatten dictionaries of list?

Using python 2.6.5, I am trying to flatten the all the lists that are attach to each dictionary key and put them as one list if possible as a one unique set. I tried with two different functions and just not sure what I need to do.

The problem I'm having is that it's not returning a list of values but list of keys.

For example:

dict = {'alpha': [[], ['dg1']],
        'beta': [[], ['dg2'], ['dg3'], ['dg4'], ['dg1']],
        'charlie': [[], ['dg1']],
        'delta': [[], ['dg4']]}

new_list = flatten(dict)

results in [alpha,beta,charile,delta] , but I want is [dg1,dg2,dg3,dg4] .

What I havve tried:

def flatten(a):
    b = []
    for c in a:
        if isinstance(c, list) and any(isinstance(i, list) for i in c):
            b.extend(flatten(c))
        else:
            b.append(c)
    return b

def flatten_list(lst):
    """
    Utility to flatten a list of list.
    If outer list is not list or None, it returns the original object.
    It will return None for None.
    """
    if not isinstance(lst, list):
        return lst
    return sum(([x] if not isinstance(x, list) else flatten_list(x)
                    for x in lst), [])

Think about the logic in this part of the code:

if isinstance(c, list) and any(isinstance(i, list) for i in c):
    b.extend(flatten(c))
else:
    b.append(c)

If c is a list without any lists inside, you're just going to append it onto b , instead of extending . So, if b = [0] and c = [1, 2] , you'll end up with b = [0, [1, 2]] .

You need to always extend if c is a list. So, you can do this:

if isinstance(c, list):
    if any(isinstance(i, list) for i in c):
        b.extend(flatten(c))
    else:
        b.extend(c)
else:
    b.append(c)

This will work. But think about what happens if you call flatten on an already-flat list, and you should be able to simplify this further.


Meanwhile, if you don't know how to flatten each value in a dict, you can do it with an explicit loop:

d = {'alpha': [[], ['dg1']], 'beta': [[], ['dg2'], ['dg3'], ['dg4'], ['dg1']], 'charlie': [[], ['dg1']], 'delta': [[], ['dg4']]}
new_d = {}
for k, v in d.items():
    new_d[k] = flatten(v)

I've used d.items() there. In Python 2.x, that gives you a new list, with all the key-value pairs for the dictionary. If the dictionary is huge, making that list just to loop over it can be wasteful, so you may want to use d.iteritems() instead, which gives you a lazy iterator instead of a list.


If you know what comprehensions are, you should recognize this pattern of "create an empty collection, loop, add to the collection" as a paradigm case for converting to a comprehension:

new_d = {k: flatten(v) for k, v in d.items()}

Unfortunately, dictionary comprehensions weren't added until 2.7. But you can get the same effect with the dict function and a generator expression:

new_d = dict((k, flatten(v)) for k, v in d.items())

Not quite as readable, but it has the same effect, and it works back to 2.4.

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