I'm writing the following:
def make_table(data: str, w: int) -> List[List]:
pass
data
is a string containing items separated by ,
. Some items may be an empty sequence so multiple commas are possible, the input can also start/end with comma which mean that first/last item is empty.
w
stands for width and is the number of columns of the output table. We're assuming the input is valid.
Examples:
In [1]: make_table("a,b,c,d,e,f,g,h,i",3)
Out[1]: [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]
In [2]: make_table(",,1,,1,,1,,",3)
Out[2]: [['', '', '1'], ['', '1', ''], ['1', '', '']]
My first working solution is this:
def make_table(data: str, w: int) -> list:
data = data.split(",")
return [data[i*w:(i+1)*w] for i in range(len(data)//w)]
What I don't like here is that
- range(len(...)) gives me bad memories
- I feel like this could be done prettier.
I know numpy could do it, but that's overkill. I'm looking through std libs but don't see anything related.
My second solution is more efficient but a little roundabout, I was looking for some lazy split solution but found only some rejected proposals. I did this:
def coma_split(data: str):
i, j = 0, -1
while True:
i, j = j + 1, data.find(",", j + 1)
if j != -1:
yield data[i:j]
else:
yield data[i:]
break
def make_3_column_table(data: str) -> list:
g = coma_split(data)
return list(zip(g,g,g))
But here I don't know how to make zip take arbitrary number of references to g.
How can I improve any of those?