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.

Community
  • 1
  • 1
Simon Lepkin
  • 1,021
  • 1
  • 13
  • 25

2 Answers2

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())
Daniel
  • 42,087
  • 4
  • 55
  • 81
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)
Community
  • 1
  • 1
Alicia Garcia-Raboso
  • 13,193
  • 1
  • 43
  • 48
  • 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. – Simon Lepkin Jul 06 '16 at 20:23