2

How can I best convert a list of lists in Python to a (for example) comma-delimited-value, newline-delimited-row, string? Ideally, I'd be able to do something like this:

>import csv

>matrix = [["Frodo","Baggins","Hole-in-the-Ground, Shire"],["Sauron", "I forget", "Mordor"]]
> csv_string = csv.generate_string(matrix)
>print(csv_string)
Frodo,Baggins,"Hole-in-the-Ground, Shire"
Sauron,I forget,Mordor

I know that Python has a csv module, as seen in SO questions like this but all of its functions seem to operate on a File object. The lists are small enough that using a file is overkill.

I'm familiar with the join function, and there are plenty of SO answers about it. But this doesn't handle values that contain a comma, nor does it handle multiple rows unless I nest a join within another join.

2

2 Answers 2

7

Combine the csv-module with StringIO:

import io, csv

result = io.StringIO()
writer = csv.writer(result)
writer.writerow([5,6,7])
print(result.getvalue())
Sign up to request clarification or add additional context in comments.

1 Comment

Ah, perfect! I was not familiar with the StringIO class. Totally worth the downvotes. :P
1

The approach in the question you link to as a reference for join, together with a nested joins (what's wrong with that?) works as long as you can convert all of the objects contained in your list of lists to a string:

list_of_lists = [[1, 'a'], [2, 3, 'b'], ['c', 'd']]
joined = '\n'.join(','.join(map(str, row)) for row in list_of_lists)
print(join)

Output:

1,a
2,3,b
c,d

EDIT:

If the string representation of your objects may contain commas, here are a couple of things you could do to achieve an output that can recover the original list of lists:

  1. escape those commas, or
  2. wrap said string representations in some flavor of quotes (then you have to escape the occurrences of that character inside your values). This is precisely what the combination of io.StringIO and csv does (see Daniel's answer).

To achieve the first, you could do

import re

def escape_commas(obj):
   return re.sub(',', '\,', str(obj))

joined = '\n'.join(','.join(map(escape_commas, row)) for row in list_of_lists)

For the second,

import re

def wrap_in_quotes(obj):
   return '"' + re.sub('"', '\"', str(obj)) + '"'

joined = '\n'.join(','.join(map(wrap_in_quotes, row)) for row in list_of_lists)

1 Comment

As I mentioned in my question, that solution doesn't handle values that themselves contain a comma. My bad, I should have provided a clear example. I'll edit.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.