Reputation:
I am looping a CSV file, which is opened as dictionary. The problem is that while I loop through the rows in the dictionary, the main for
loop goes to the next item. The dictionary does not reset to the first item when running the for
loop. So if it gets to the last row, it doesn't change.
names = ['a', 'b', 'c', 'd', 'e', 'f']
source1_csv = open("output.csv", mode='r')
dictionary_csv = csv.DictReader(source1_csv)
for letters in names:
for entry in dictionary_csv:
print(entry["name"])
if entry['name'] == letters:
print("found it")
You can use any CSV file, just replace the key in the entry
, and notice that if there is no match on the outer for
loop, once that the next item in the names
is selected, the inner for loop for the dictionary will just exit because the dictionary is already on the last position and does not reset.
How do I avoid this, so the position of the dictionary is reset and parse through every row for every entry of the names list?
Upvotes: 2
Views: 771
Reputation: 2703
Solution 1:
From your code above, it doesn't look like that you need to iterate over the entire csv multiple times, you can just switch the loops like:
for entry in dictionary_csv:
for letters in names:
print(entry["name"])
if entry['name'] == letters:
print("found it")
Switching the loop over dictionary_csv
to outer loop will avoid looping over csv multiple times.
Solution 2:
But if you don't want to change the order of loops, you can simply convert the DictReader
to list
before consuming it yourself. This way, list
will consume the reader, and return you a list of it, and you can iterate over it multiple times:
dictionary_csv = list(csv.DictReader(source1_csv))
But if your csv is rather big, creating a list out of it isn't recommended, as list size will be big.
Solution 3:
Instead of creating a list, you can also seek the source file source1_csv
to 0 before the inner loop:
for letters in names:
source1_csv.seek(0)
for entry in dictionary_csv:
print(entry["name"])
if entry['name'] == letters:
print("found it")
It will take the source file to the start, and dictionary_csv
will read it again for you.
Edit:
As @merlyn pointed out in below comments, that the solution 3 will not work entirely correctly, because after seeking to 0, dictionary_csv
will interpret the first line of the csv (headers) as a separate data row. So, you'll have to ignore a line after seeking to 0.
source1_csv.seek(0)
source1_csv.readline()
Or, re-instantiate dictionary_csv
everytime you seek source1_csv
(For that, you can see @merlyn's answer below).
Upvotes: 1
Reputation: 2361
csv
doesn't provide a way to reset the iterator but the file object interface does. You can reset a file to it's starting position using file.seek(0)
.
names = ['a', 'b', 'c', 'd', 'e', 'f']
source1_csv = open("output.csv", mode='r')
for letters in names:
source1_csv.seek(0)
for entry in csv.DictReader(source1_csv):
print(entry["name"])
if entry['name'] == letters:
print("found it")
Of course, you can also store the entries in a list and iterate on the as many time as you want. But that won't with files too large to store in memory.
Upvotes: 1