Write a list of common dictionaries to CSV with common key values in the same column

I have a list of dictionaries constructed so that each dictionary would represent data for a particular event. the data is:

events = [{'date': '7:30 PM ET, October 29, 2014',
      'guests': ['Cleopatra', 'Ghandi'], 
      'location': 'Cairo, Egypt',
      'random_nums': [1, 2, 3, 4]},
     {'date': '8:00 PM ET, November 1, 2014', 
      'guests': ['JFK', 'Abe Lincoln'], 
      'location': 'Dallas, TX', 
      'random_nums': [5, 6, 7, 8]},
     {'date': '8:30 PM ET, November 3, 2014', 
      'guests': ['Joan of Arc', 'Genghis Khan'], 
      'location': 'the Moon',
      'random_nums': [9, 10, 11, 12]}]

I am trying to write to a CSV so that each even is represented as its own row, with the common keys as headers.

date                    random_nums    guests                    location
7:30 PM ET, October 29  1, 2, 3, 4     Cleopatra, Ghandi         Cairo, Egypt
8:00 PM ET, November 1  5, 6, 7, 8     JFK, Abe Lincoln          Dallas, TX
8:30 PM ET, November 3  9, 10, 11, 12  Joan of Arc, Genghis Khan the Moon

I've looked at a lot of similar posts on this topic but none solve this particular issue. I realize that there is some delimiter problem since there are commas in the strings.

So, I need help:

  1. making each event a row (lists should be contained in a single element)
  2. solving my delimiter issue without changing the commas in the strings or some workaround

Here's as close as I've gotten:

with open("output.csv", "wb") as f:
    writer = csv.writer(f, delimiter = ';')
    writer.writerow(list(events[1].keys()))
    for event in events:
        print event.values()
        for row in event.values():
            writer.writerow(row)

Answers


Since you have a bunch of dictionaries, it might be a little simpler to use csv.DictWriter, which will automatically align the keys. Something like

with open("output.csv", "wb") as f:
    writer = csv.DictWriter(f, fieldnames=list(events[0]), delimiter = ';')
    writer.writeheader()
    for event in events:
        outevent = event.copy()
        outevent["random_nums"] = ", ".join(map(str, outevent["random_nums"]))
        outevent["guests"] = ", ".join(outevent["guests"])
        writer.writerow(outevent)

will produce

date;random_nums;guests;location
7:30 PM ET, October 29, 2014;1, 2, 3, 4;Cleopatra, Ghandi;Cairo, Egypt
8:00 PM ET, November 1, 2014;5, 6, 7, 8;JFK, Abe Lincoln;Dallas, TX
8:30 PM ET, November 3, 2014;9, 10, 11, 12;Joan of Arc, Genghis Khan;the Moon

Note though that you could use tabs or even commas as the delimiters as well-- if the delimiter exists in an element it'll be appropriately quoted.


Need Your Help

Which Knockout.js bindings are “Two-way”?

javascript knockout.js

Knockout.js boasts two-way bindings, and the live examples show how the value binding (when applied to a text input) updates the viewmodel.

Set regular HTTP request headers from javascript

javascript authentication http-headers jwt

I'm trying to make a multipage web app that uses json web tokens for authentication. Using JWTs for single page apps is fairly trivial as you just set the headers on an XHR and send it off, but s...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.