添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

I have a python dictionary which for each KEY one can have a variable number of VALUES (arranged in a list).

For example:

{'607': [36146], '448': [50890, 44513], '626': [44349, 44436]}

What I'd like to do is generate a CSV of this information with a format like so:

 448 , 607 , 626
50890,36146,44349
44513,     ,44436

Currently my code can produce a CSV such as this, the only issue being that the columns of the CSV are not sorted according to the ascending numerical order of the KEYs. My code so far is below:

csv_file = 'file.csv'
with open(csv_file, 'wb') as fd:
    writer = csv.writer(fd, delimiter = ',')
    # Format headers for aesthetics
    csv_headers = [' {} '.format(elem) for elem in dictionary.keys()]
    writer.writerow(headers)
    # Format data to create convenient csv format
    csv_data = itertools.izip_longest(*dictionary.values(), fillvalue = '     ')
    writer.writerows(csv_data)

As you can see I split the KEYs from the VALUEs and write them separately but if I want to sort the columns by the KEYs I imagine this is probably not the best way to go about this. Therefore, I was hoping someone could point me in the right (and most pythonic) direction.

  • Sort the keys, then extract values in the same order rather than rely on dictionary.values()
  • Use a csv.DictWriter() object and produce dictionaries per row.
  • Option 1 looks like this:

    csv_file = 'file.csv'
    with open(csv_file, 'wb') as fd:
        writer = csv.writer(fd, delimiter=',')
        keys = sorted(dictionary) 
        # Format headers for aesthetics
        headers = [' {} '.format(key) for key in keys]
        writer.writerow(headers)
        # Format data to create convenient csv format
        csv_data = itertools.izip_longest(*(dictionary[key] for key in keys),
                                          fillvalue='     ')
        writer.writerows(csv_data)
    

    Using DictWriter would look like:

    csv_file = 'file.csv'
    with open(csv_file, 'wb') as fd:
        writer = csv.DictWriter(
            fd, sorted(dictionary), delimiter=',')
        # write formatted headers
        writer.writerow({k: ' {} '.format(k) for k in dicitonary})
        csv_data = itertools.izip_longest(*dictionary.values(), fillvalue='     ')
        writer.writerows(dict(zip(dictionary, row)) for row in csv_data)
                    How would I do the above with the uneven nature of my dictionary? I had attempted to use csv.Dictwriter but it didn't play well with the variable number of entries per list...
                        – user1182556
                    Nov 6 '14 at 12:34
                    Great! Option 1 works like a charm, however, Option 2 doesn't write the header values? Also, in your opinion which is the more pythonic method?
                        – user1182556
                    Nov 6 '14 at 12:53
                    Thanks for that. While I think Option 2 is probably the most pythonic as you're using DictWriter - its upsetting to the OCD part of me that I can't format the headers :(
                        – user1182556
                    Nov 6 '14 at 13:06
                    @user1182556: I had put in formatted headers but had overlooked that the fieldnames must be valid keys; I replaced the writeheader() call instead. You are free to write your own row still, just as long as it is a dictionary with the fieldnames as keys.
                        – Martijn Pieters
                    Nov 6 '14 at 13:08
    

    I went for sorting and ending up with a transposed tuple of key and an iterable of the lists, then went from there:

    import csv
    from itertools import izip_longest
    d = {'607': [36146], '448': [50890, 44513], '626': [44349, 44436]}
    with open('output.csv', 'wb') as fout:
        csvout = csv.writer(fout)
        header, rows = zip(*sorted((k, iter(v)) for k, v in d.iteritems()))
        csvout.writerow(format(el, '^5') for el in header)
        csvout.writerows(izip_longest(*rows, fillvalue='     '))
                    Nice, but the iter() calls are redundant here. It doesn't matter if you store a list reference or an list iterator object reference, but the latter will be created anyway by izip_longest().
                        – Martijn Pieters
                    Nov 6 '14 at 14:10
            

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.

    site design / logo © 2019 Stack Exchange Inc; user contributions licensed under cc by-sa 3.0 with attribution required. rev 2019.5.21.33788