Reputation: 47
I'm working with CSV files and here is what I have so far. I get an error that my index is out of range. It finishes the first for loop and then messes up. I am trying to populate a dictionary.
def read_table(file):
line = file.readline()
line = line.strip()
keylist = line.split(',')
d = {}
for key in keylist:
if key not in d:
d[key] = []
while line != '':
line = file.readline()
line = line.strip()
val = line.split(',')
for i in keylist:
index = keylist.index(i)
d[keylist[index]].append(val[index])
return d
Upvotes: 1
Views: 419
Reputation: 366123
Your while
loop isn't going to break as soon as line
becomes empty, it's just going to check that at the start of each loop.
So, when you've read all but the last line, you do this:
while line != '': # the last line wasn't empty
line = file.readline() # but now this one is
line = line.strip()
val = line.split(',') # so this returns a single value
for i in keylist:
index = keylist.index(i) # so this raises an IndexError
d[keylist[index]].append(val[index])
The smallest fix is to put the check directly after each readline
:
while True:
line = file.readline()
line = line.strip()
if not line:
break
val = line.split(',') # so this returns a single value
for i in keylist:
index = keylist.index(i) # so this raises an IndexError
d[keylist[index]].append(val[index])
(Note that if there's a blank line in the middle of your file, you will return early instead of raising an error, because you're checking line
after the line = line.strip()
, so you can no longer distinguish between an empty line, '\n'
, and end-of-file, ''
. If that's a problem, just move the test up one line.)
A better fix would be to just iterate over the file: for line in file:
does exactly what you want the loop to do, without having to deal with readline
and checking for empty strings and break
ing from a loop and so on.
But a much better fix would be to use the csv
module and let it do what it does:
d = defaultdict(list)
reader = csv.DictReader(file)
for line in reader:
for key, value in line.items():
d[key].append(value)
return d
Or, alternatively, just build a list of dicts (which you can do with list_o_dicts = list(reader)
), then convert it to a dict of lists at the end.
Upvotes: 2