China Diapers
China Diapers

Reputation: 81

Unable to iterate "csv.reader" repeatedly - empty result on second iteration

I have created list1 to include the unique values from a particular column by appending values identified as unique to it in order to perform a sort of "sum if".

Below is the scenario I am struggling with, the inner loop, iterating through the csv rows is only executing once. Is there some special characteristic that makes iterating through rows in a csv file in the inner loop of a nested loop problematic?

csv contents:

Field1
row1
row2
row3

Code:

datafile = open(r"my_file.csv", "r")
myreader = csv.reader(datafile, delimiter=",")

list1 = ["A", "B", "C"]

for x in list1[:]:
    print(x)
        for y in myreader:
               print(y)

Expected result:

A
row1
row2
row3
B
row1
row2
row3
C
row1
row2
row3

Actual result:

A
row1
row2
row3<
B
C

It appears only the initial iteration of the inner loop is working.

If I replace the csv with another list it works fine:

datafile = open(r"my_file.csv", "r")
myreader = csv.reader(datafile, delimiter=",")

list1 = ["A", "B", "C"]
list2 = ["row1", "row2", "row2"]

for x in list2[:]:
    print(x)
        for y in list2:
               print(y)

gives expected result

And I can iterate through the csv rows in a single loop no problem with the below:

x = 0
for y in myreader:
        x = x + 1
        print(y[2] + " INNER")

So why won't it all work together?

Upvotes: 3

Views: 2452

Answers (3)

Moinuddin Quadri
Moinuddin Quadri

Reputation: 48067

csv.reader returns an reader object which is an iterator. So, once you iterate the entire list, it becomes empty. You need to save your reader as a list in order to iterate it repeatedly.

In order to achieve this, you need to change:

myreader = list(csv.reader(datafile, delimiter=","))
#           ^ it'll save `myreader` as list

Hence, you complete code should be:

datafile = open(r"my_file.csv", "r")
myreader = list(csv.reader(datafile, delimiter=","))    
#           ^ converting the `iterator` to list type

list1 = ["A", "B", "C"]

#            v  I removed "[:]" from here because it is not required
#            v  `list1[:]` creates a copy of the list "list1". You 
#            v  don't need copy here
for x in list1:
    print(x)
    for y in myreader:
        print(y)

Upvotes: 8

Mike M&#252;ller
Mike M&#252;ller

Reputation: 85442

myreader is an iterator and will be exhausted after the first iteration. Convert it into a list to get your desired output.

csv_rows = list(myreader)
for x in list1[:]:
    print(x)
        for y in csv_rows:
               print(y)

Iterators allow only one iteration. On the other hand, a list can be iterated over again and again. The advantage of the iterator is that does not load all elements into memory at once. This can be important if the file is large. In this case, the list might consume considerable amounts of memory.

Upvotes: 1

Patrick Artner
Patrick Artner

Reputation: 51643

After your loop with A your reader iterator is BEHIND all the data. You would have to reposition it to the start but why do you do this?

It would be better to save all the data once into a list and then reuse that.

myData = list(myreader) # this will iterate the whole file and put all in a list.

See https://docs.python.org/3/library/csv.html

Upvotes: 1

Related Questions