1

I need to write lists that all differ in length to a CSV file in columns.

I currently have:

d=lists
writer = csv.writer(fl)
for values in zip(*d):
    writer.writerow(values)

which works only partially. What I suspect is happening is that it stops zipping up until the lists with the list of the shortest length.

Sameer Patel
  • 927
  • 3
  • 16
  • 20
  • What programming language do you use and what csv lib? – Konstantin V. Salikhov Jul 30 '14 at 17:33
  • Your issue is with how you are using zip. Check out this answer: http://stackoverflow.com/questions/19686533/how-to-zip-two-different-size-list-in-python – Krets Jul 30 '14 at 18:25
  • @Krets I'm not sure that's the same question, though; the solutions there repeat the lists (like in `R`). – Al.Sal Jul 30 '14 at 18:29
  • Also, `d` is just a list of lists, right? – Al.Sal Jul 30 '14 at 18:31
  • yes, d is a list of lists – Sameer Patel Jul 30 '14 at 18:32
  • @Al.Sal You are correct. The answer I linked to relates to only two lists whereas this is for a list of lists. Regardless, the issue remains zip() will return a list that matches the length of the shortest input list. Sameer must manipulate all the lists to be the same length before using zip. The first answer seems like it would get it done. – Krets Jul 30 '14 at 18:42
  • Hm. Then why not transpose the lists first? That would clean up code readibility-wise. – Al.Sal Jul 30 '14 at 18:49

2 Answers2

10

Code below is for Python 3. If you use Python 2, import izip_longest instead of zip_longest.

import csv
from itertools import zip_longest

d = [[2,3,4,8],[5,6]]

with open("file.csv","w+") as f:
    writer = csv.writer(f)
    for values in zip_longest(*d):
        writer.writerow(values)

Result:

2,5
3,6
4,
8,
Christer Nissen
  • 487
  • 2
  • 6
2

There's no 'neat' way to write it since, as you said, zip truncates to the length of the shortest iterable.

Probably the simplest way would be to just pad with None or empty strings (Not sure offhand what the behavior of writerow is with None values):

maxlen = max([len(member) for member in d])
[member.extend([""] * (maxlen - len(member))) for member in d]
for values in zip(*d):
    ...

Alternatively, you could just construct each row inside the for loop instead of using zip, which would be more efficient but a lot wordier.

EDIT: corrected example

Mark Whitfield
  • 2,470
  • 1
  • 12
  • 12