Reputation: 703
List l
contains items consisting of two types of lists, the first being acceptable lists consisting of strings and the second consisting of strings of tuples containing strings. All lists of the second type are of the same length - 2. I want to convert all lists of the second type to the same convention as the first type, as demonstrated below (l2
is the updated list).
Edit: I should clarify that the actual list I am dealing with as far more than two items, so I need a loop function to accommodate this.
l = [["('N', '', 'SHOWERS', '', 'RD', '11734', '11734', '', '')", "('61060', '61060')"], ['', '', 'NORA', '', 'RD', '10301', '10999', '10400', '10998', '61089', '61089']]
l2 = [['N', '', 'SHOWERS', '', 'RD', '11734', '11734', '', '', '61060', '61060'], ['', '', 'NORA', '', 'RD', '10301', '10999', '10400', '10998', '61089', '61089']]
The following only gets me so far:
from csv import reader
from cStringIO import StringIO
l2 = []
for i in l:
if len(i) == 2:
filestr = StringIO(i[0] + i[1])
csv_reader = reader(filestr, quotechar="'")
for t in csv_reader:
l2.append(t)
else:
l2.append(i)
Upvotes: 0
Views: 345
Reputation: 31621
This is not a csv problem, since you don't have a csv. (In fact you confused me for some time because I was trying to imagine what the csv file looked like!)
is_tuple_string_row
function below).ast.literal_eval
to safely convert the string-of-tuple into an actual tuple.chain.from_iterable
to combine all the tuples into a single sequence.Full code below implemented as the generator normalized_list()
.
l = [["('N', '', 'SHOWERS', '', 'RD', '11734', '11734', '', '')", "('61060', '61060')"], ['', '', 'NORA', '', 'RD', '10301', '10999', '10400', '10998', '61089', '61089']]
l2 = [['N', '', 'SHOWERS', '', 'RD', '11734', '11734', '', '', '61060', '61060'], ['', '', 'NORA', '', 'RD', '10301', '10999', '10400', '10998', '61089', '61089']]
import ast
from itertools import imap, chain
def is_tuple_string_row(L):
"""Return whether list L is a list of strings containing tuples"""
return len(L)==2 and all(s.startswith("('") and s.endswith("')") for s in L)
def normalized_list(L):
"""Yield lists in sequence L as lists of strings
Normalizes a list of strings of tuples down to a simple list of strings
"""
for item in L:
if is_tuple_string_row(item):
yield list(chain.from_iterable(imap(ast.literal_eval, item)))
else:
yield item
# You can iterate efficiently
for item in normalized_list(l):
print item
# or you can put the whole thing to a single new list
aslist = list(normalized_list(l))
# verify results
assert aslist == l2
Upvotes: 1
Reputation: 35522
You can use ast:
>>> import ast
>>> l = [["('N', '', 'SHOWERS', '', 'RD', '11734', '11734', '', '')", "('61060', '61060')"], ['', '', 'NORA', '', 'RD', '10301', '10999', '10400', '10998', '61089', '61089']]
>>> l2=[e for e in ast.literal_eval(l[0][0])]
>>> l2+=[e for e in ast.literal_eval(l[0][1])]
>>> l2=[l2]
>>> l2.append(l[1])
>>> l2
[['N', '', 'SHOWERS', '', 'RD', '11734', '11734', '', '', '61060', '61060'], ['', '', 'NORA', '', 'RD', '10301', '10999', '10400', '10998', '61089', '61089']]
As you may know, eval
has some real security issues. ast
is quite safe since it can only produce Python base data structures.
Upvotes: 2
Reputation: 20770
I would recommend working with Lists instead of Tuples, and then indexing the lists / sublists / and sublists of list if necessary to achieve what you want.
Another Idea would be to make a Class of the structure that you want. Put methods that slice the list. It appears that you want the first 9 items in a tuple, and the last two in a separate tuple. This would be a good way to separate them out as well.
Upvotes: 0
Reputation: 185842
If, and only if, you trust the input, you can eval it:
l2 = eval(l[0][0])
I don't fully understand the structure of the entire input, so I can't help you with looping over all of it.
Upvotes: 1