3

This stackoverflow question answers to write a dictionary of lists into a CSV file. My use case is to write a similar dictionary of lists into a CSV string instead of a file. If I do following

csvfile += ",".join(csvdata.keys())
for values in csvdata.values():
    csvfile += ",".join(value for value in values) + "\n"

It is giving me all lists expanded in different rows. Instead, I am looking for an output with dictionary key as a column header and same key's values (in the list) as its column values.

Input
{'ID' :['101','102'], 'Name': ['X','Y'],'Gender': ['M','F']}

Expected Output (In comma separated string)
ID,   Name, Gender
101,  X,    'M'
102,  Y,    'F'

Output with my code
ID, Name, Gender
101, 102,
X,   Y,
'M', 'F',

Edit #1 : Explaining the duplicate request here. Question "How do I write data into csv format as string (not file)?" is for a different use-case, my question is rather for a specific one.

Georgy
  • 12,464
  • 7
  • 65
  • 73
Saurabh Saxena
  • 3,005
  • 10
  • 31
  • 46
  • 1
    I’m voting to close this question because it is unlikely to help future visitors and is misleadingly titled; the underlying question is actually about how to manipulate the data structure. The overall task, as described, should still be solved using the `csv` and `StringIO` modules as described in the last linked answer - just rearrange the data properly first. – Karl Knechtel May 26 '22 at 23:22

2 Answers2

4

Each of the values in csvdata.values() is a list of values for its corresponding key / column, so you are effectively printing the columns of the table as rows.

Instead, construct the rows by ziping the value lists:

csvfile += ",".join(csvdata.keys()) + "\n"
for row in zip(*csvdata.values()):
    csvfile += ",".join(row) + "\n"

Output:

ID,Name,Gender
101,X,M
102,Y,F
meowgoesthedog
  • 14,670
  • 4
  • 27
  • 40
  • Thanks for the response. This turned out to store only the first row, I am trying to debug it, meanwhile if you know the exact reason, please point out. – Saurabh Saxena Apr 29 '19 at 10:35
  • @SaurabhSaxena works fine on my end with the sample input you provided. Check the contents of `csvdata`. – meowgoesthedog Apr 29 '19 at 10:38
  • csvdata looks identical to the input I gave, can you tell me the importance of '*' in the call zip(*csvdata.values()) – Saurabh Saxena Apr 29 '19 at 10:52
  • @SaurabhSaxena see [this post](https://stackoverflow.com/questions/2921847/what-does-the-star-operator-mean). It passes the value lists in `csvdata` as separate arguments to `zip`, as it requires. – meowgoesthedog Apr 29 '19 at 10:54
0

Instead of performing manipulations with strings (joining them with commas and linebreaks) I suggest a more idiomatic and cleaner approach using a csv module and io.String:

import csv
import io


data = {'ID': ['101', '102'], 'Name': ['X', 'Y'], 'Gender': ['M', 'F']}

with io.StringIO() as output:
    writer = csv.writer(output)
    writer.writerow(data.keys())
    writer.writerows(zip(*data.values()))
    result = output.getvalue()
print(result)

This gives:

ID,Name,Gender
101,X,M
102,Y,F


References:

Georgy
  • 12,464
  • 7
  • 65
  • 73