Homunculus Reticulli
Homunculus Reticulli

Reputation: 68486

Pythonic way to flatten a dictionary into a list using list comprehension

I have the following function:

def create_list_from_dict1(mydict):
    output = []
    for k, v in openint_dict.items():
        output.append( (k, v['field1'], v['field2'], v['field3']) )

    return output

Essentially, it flattens the dictionary, so that I can perform sorting on one of the fields of the tuple in the returned list.

I don't like the fact that I am having to 'hard code' the field names of the value dictionary ('field1', ..., 'fieldN'), and I want a more pythonic and elegant way of doing this so that this function works for all dictionaries that contain a fixed structure (non-nested) dictionary as its values.

I imagine that I will have to use **kwargs and/or a lambda function, as well as list comprehension. What would be the most pythonic way to write this function?

Upvotes: 6

Views: 19535

Answers (6)

Mad Physicist
Mad Physicist

Reputation: 114588

Python dicts have keys() and values() methods to get a list of the keys and values. If order of the fields is not important:

[(k,) + tuple(v.values()) for k, v in mydict.items()]

If the ordering of the values does matter:

[(k,) + tuple(v[i] for i in sorted(v)) for k, v in mydict.itemd()]

Note that the second option would be identical to the first without the call to sorted(). The order depends on how things were added to the subdict, so you should use the second option as much as possible.

Upvotes: -1

King110
King110

Reputation: 122

I think this would be pythonic:

[(k, v) for k, v in dict_data.items()]

Upvotes: 0

B. M.
B. M.

Reputation: 18668

def create_list_from_dict1(mydict):
    return [tuple([k]+list(v.values())) for k,v in openint_dict.items()]

doesn't use the fields' names and produces the same result.

In Python 3.5, you can just type (because starred expressions are allowed everywhere):

def create_list_from_dict1(mydict):
    return [(k,*v.values()) for k,v in openint_dict.items()]

Upvotes: 0

jonrsharpe
jonrsharpe

Reputation: 122157

This might solve your problem:

def create_list_from_dict1(mydict):
    return [
        (key,) + tuple(v for _, v in sorted(val.items()))
        for key, val in sorted(mydict.items())
    ]

This assumes that:

  • You want the same order for the values in each tuple in the output;
  • You want the outer and inner keys sorted alphabetically (otherwise you'll need an appropriate key for sorted);
  • You want the values for all of the keys from the inner dictionaries; and
  • All of the dictionaries in the input contain all of the same keys (otherwise you'll get more/fewer entries in each tuple, and no guarantee they're aligned).

Note the use of .items in both inner and outer loops to sort both by key (two-tuples are sorted on the first element, with the second only used to break ties) and the conventional _ identifier for "we won't be using this any more".

In use:

>>> create_list_from_dict1({
    'hello': {'foo': 1, 'bar': 2, 'baz': 3},
    'world': {'foo': 4, 'bar': 5, 'baz': 6},
})
[('hello', 2, 3, 1), ('world', 5, 6, 4)]

Upvotes: 4

Eugene Soldatov
Eugene Soldatov

Reputation: 10145

You can do it like this:

fields = ("field1", "field2", "field3")

output = [[k] + [mydict[k].get(x) for x in fields] for k in mydict]

In that code we iterate dict keys and add them with selected subset of second-level dictionaries values.

Upvotes: 5

0of1
0of1

Reputation: 376

If order doesn't matter...

def create_list_from_dict1(mydict):
    output = []
    for k, v in openint_dict.items():
        fields = [value for key, value in v.items()]
        output.append( tuple([k] + fields )

    return output

If order matters you either need to do as you did and call out the fields specifically...or you need to used an OrderedDict for the sub-dicts.

Upvotes: 0

Related Questions