[Tutor] list of dicts <-> dict of lists?

Mark Lawrence breamoreboy at yahoo.co.uk
Fri May 28 01:29:04 CEST 2010


I confess that I don't like top posting :)  Please see below.

On 28/05/2010 00:19, Matthew Wood wrote:
> #!/usr/bin/env python
>
>
> Here's my best attempt.  I'm not sure if it's "simpler" than yours,
> but for me it seems a bit cleaner.  Then again, I LOVE the zip
> operator, and the '*' operator too.  :-)  Whenever I see a "transpose
> this" type problem, I think zip.
>
>
> y = {'a': [1, 2, 3], 'c': [7, 8, 9], 'b': [4, 5, 6]}
>
> print y
>
> old = [dict([(i, y[i][j]) for i in y.keys()])
>                            for j in range(len(y[y.keys()[0]]))]
> print old
>
>
> keys, values = zip(* y.items())
> new = [dict([(i, j) for i, j in zip(keys, column)])
>                      for column in zip(* values)]
>
> print new
>
> print new == old
>
> I BELIEVE there's some new cool features in 2.6 or maybe 3.0 where
> non-simultaneous access to my_dict.keys() and my_dict.values() will
> keep them "paired up", but I don't know the details.  If you skipped
> the upper line (setting keys and values) you'd be accessing y.keys() 3
> times (in this example).  I'm not sure if you're guaranteed to have
> the order remain the same for all three accesses.  If that's the case,
> I'd change the code to be:
>
> # This line isn't necessary #keys, values = zip(* y.items())
> new = [dict([(i, j) for i, j in zip(y.keys(), column)])
>                      for column in zip(* y.values())]
>
> or even
>
> # This line isn't necessary #keys, values = zip(* y.items())
> new = [dict([(i, j) for i, j in zip(y, column)])
>                      for column in zip(* y.values())]
>
>
RTFM? :)  From the Python docs for 2.6.5
"items()
Return a copy of the dictionary’s list of (key, value) pairs.

CPython implementation detail: Keys and values are listed in an 
arbitrary order which is non-random, varies across Python 
implementations, and depends on the dictionary’s history of insertions 
and deletions.

If items(), keys(), values(), iteritems(), iterkeys(), and itervalues() 
are called with no intervening modifications to the dictionary, the 
lists will directly correspond. This allows the creation of (value, key) 
pairs using zip(): pairs = zip(d.values(), d.keys()). The same 
relationship holds for the iterkeys() and itervalues() methods: pairs = 
zip(d.itervalues(), d.iterkeys()) provides the same value for pairs. 
Another way to create the same list is pairs = [(v, k) for (k, v) in 
d.iteritems()]."

> But since I'm a coward, and I'd like my code to run on older versions
> of python too, I'd leave the initial step.
> --
>
> I enjoy haiku
> but sometimes they don't make sense;
> refrigerator?
>
>
> On Thu, May 27, 2010 at 4:15 PM, David Perlman<dperlman at wisc.edu>  wrote:
>>
>> Using the csv.DictReader and csv.DictWriter lets you read and write lists of dictionaries from files containing tabular data.  I have a system that naturally generates tabular data in the form of a dictionary of lists: the dictionary key is the name of the column, and then the value is a list which contains the data for that column.  Sort of like a spreadsheet.  I would like to use csv.DictWriter to write out this data but that requires a list of dicts.
>>
>> I can convert the dict of lists to a list of dicts, and thus make it compatible with csv.DictWriter, with the following ugly comprehensions:
>>
>>>>> y
>> {'a': [1, 2, 3], 'c': [7, 8, 9], 'b': [4, 5, 6]}
>>>>> [dict([(i,y[i][j]) for i in y.keys()]) for j in range(len(y[y.keys()[0]]))]
>> [{'a': 1, 'c': 7, 'b': 4}, {'a': 2, 'c': 8, 'b': 5}, {'a': 3, 'c': 9, 'b': 6}]
>>
>> ...but I'm wondering if anyone knows of a more elegant way, perhaps something built-in suited for this purpose...
>>
>> I am aware that any solution will only work if the lists in the dict are all the same length.  :)
>>
>> Thanks!
>>
>>
>> --
>> -dave----------------------------------------------------------------
>> "Pseudo-colored pictures of a person's brain lighting up are
>> undoubtedly more persuasive than a pattern of squiggles produced by a
>> polygraph.  That could be a big problem if the goal is to get to the
>> truth."  -Dr. Steven Hyman, Harvard
>>
>>
>>
>> _______________________________________________
>> Tutor maillist  -  Tutor at python.org
>> To unsubscribe or change subscription options:
>> http://mail.python.org/mailman/listinfo/tutor
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> To unsubscribe or change subscription options:
> http://mail.python.org/mailman/listinfo/tutor
>




More information about the Tutor mailing list