Dict to "flat" list of (key,value)

David C. Fox davidcfox at post.harvard.edu
Wed Jul 30 16:38:11 EDT 2003


Nicolas Girard wrote:
> Hi,
> 
> Forgive me if the answer is trivial, but could you tell me how to achieve
> the following:
> 
> {k1:[v1,v2],k2:v3,...} --> [[k1,v1],[k1,v2],[k2,v3],...]
> 
> The subtle point (at least to me) is to "flatten" values that are lists.

Well, I can get you at least part way, but there is an ambiguity in your 
original data structure which causes problems:

1.  d.items() will get you

[(k1, [v1, v2]), (k2, v3), ...]

2.  Now, you want to expand out the list elements where the second part 
of each tuple is a list, which you can do with.

     flatten = lambda u: map(lambda x: (u[0], x), u[1])

or, if the double lambda expression is confusing:

     def flatten(u):
         return map(lambda x: (u[0], x), u[1])

(I've used a tuple (u[0], x) instead of a list, because your [k1, vn] 
are always pairs, but you can use a list if you prefer)

Then flatten will take the nested element

     (k1, [v1, v2])

and convert it to a list of tuples

     [(k1, v1), [k2, v2])]

3.  You want to apply flatten to each element of d.items(), which you 
can do with

     lol = map(flatten, d.items())

which will give you a list of lists of tuples,

4.  and then reduce that to a list of tuples with

     reduce(operator.add, lol)


Unfortunately, this doesn't quite work with your example above, because 
flatten won't work properly when applied to (k2, v3).  If v3 is a 
sequence, it will instead give you [(k2, v3[0]), (k2, v3[1]), ...], 
which is probably not what you want (especially if v3 is a string - try 
flatten manually and see what happens).  If v3 is not a sequence, you'll 
get a TypeError saying that argument 2 to map() must support iteration.

If you *know* that v3 will NEVER be a list, you can modify flatten to 
handle the special case like so:

     def flatten(u):
         if isinstance(u[1], type([])):
             return (u[1], [u[2]])
         return map(lambda x: (u[0], x), u[1])

Alternatively, if you can modify how the initial dictionary is generated 
to ensure that cases where a key has a single value always appear as
k2: [v3] instead of k2: v3, then you can use the steps above without 
modification.  This is probably better if it is feasible, because your 
original data structure is inherently ambiguous unless you know that v3 
will never be a list.

David




> 
> Thanks in advance,
> Nicolas
> 
> 
> 
> ----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
> http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
> ---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---





More information about the Python-list mailing list