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.
In : make_table("a,b,c,d,e,f,g,h,i",3) Out: [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']] In : make_table(",,1,,1,,1,,",3) Out: [['', '', '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?